Хотя я могу правильно разобрать эту полезную нагрузку, если я укажу ключи через нотацию с помощью скобок, как бы вы могли разобрать ее динамически?
{
"name": "Demo User",
"birthday": "January 1st",
"hobbies":
{
"morning": "coding",
"afternoon": "kewl kids stuff",
"nighttime": "random"
},
"date": "June 25th"
}
Я имею в виду, что хобби могут быть не там, иначе может существовать другое поле, такое как "любимые продукты", которое может быть массивом или объектом.
Этот сценарий вызвал у меня много разочарований в последние пару месяцев, и я пытаюсь понять, может ли кто-нибудь объяснить мне, как успешно его разобрать, динамически.
Я нашел рекурсивный подход "ходьбы", который больше не является ошибкой, но он возвращает первое, что встречается для каждой итерации.
var data = require("./demo.json");
//data = JSON.stringify(data);
function walk(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var val = obj[key];
console.log(val);
walk(val);
}
}
}
walk(data);
Основываясь на том, что я нашел, данные импортируются как JSON, и если я его строкую, он становится строкой (очевидно).
По умолчанию
{ name: 'Demo User',
birthday: 'January 1st',
hobbies:
{ morning: 'coding',
afternoon: 'kewl kids stuff',
nighttime: 'random' },
date: 'June 25th' }
Stringify
{"name":"Demo User","birthday":"January 1st","hobbies":{"morning":"coding","afternoon":"kewl kids stuff","nighttime":"random"},"date":"June 25th"}
Оба они похожи, но единственная разница в выходе - это спам D
X раз (будучи первым значением, я думаю?) Или спамом {
X раз (Являясь первым значением строки?
Я пробовал гораздо более фундаментальный подход
var data = require("./demo.json");
for (var key in data){
console.log(key + ':' + data[key]);
}
Это работает нормально, но, как и ожидалось, хобби возвращают [object Object]
так как я не повторяю его. Я мог бы заниматься hobbies
, но опять же - я не знаю, будет ли это существовать.
Приветствуем любой ввод - общий вопрос, но процесс, который вызвал у меня много разочарований по различным проектам за последние несколько месяцев.
ОБНОВИТЬ
Моя неопределенность вызывает, по праву, путаницу.
Скажем, моя цель - превратить эту полезную нагрузку JSON в CSV. Мне нужен каждый ключ для заголовков, а каждое значение - строка под заголовком. Моя проблема заключается в том, что, перейдя через нее, я получаю правильно преобразованные объекты высшего уровня. Затем я получаю столбец Object Object без данных.
Для этого точного примера, скажем, моя цель - преобразовать JSON в
name, birthday, hobbies/morning, hobbies/afternoon, hobbies/nighttime, data
Demo User, January 1st, coding, kewl kids stuff, random, June 25th
Обновление # 2
Дополнительный вариант array
.
Я бы ожидал
{
...
"hobbies":
{
"morning": "coding",
"afternoon": "kewl kids stuff",
"nighttime": "random"
},
...
}
Выводить hobbies/morning, hobbies/afternoon, hobbies/nighttimes
Я бы ожидал
{
...
"hobbies": ["coding", "kewl kids stuff", "coding"]
...
}
Для вывода одного столбца hobbies
с цитатой-вложенные элементы "coding, kewl kids stuff, coding"
Попробуйте использовать эту функцию (фрагмент в конце ответа)
/**
*
* @param {object} input
* @returns {Array<string>}
*/
function translateObject(input) {
if (typeof input === "object" && input !== null) {
if (input instanceof Array) {
var result = '"';
for (var index in input) {
if (index) result += ", ";
result += input[index];
}
return [result + '"'];
} else {
var data = "", result = "";
for (var key in input) {
if (key.includes(",")) {
throw new Error("Key cannot have a comma");
}
var val = translateObject(input[key]);
if (val.length === 2) {
var titles = val[0].split(", ");
var textIndex = 0;
var size = 0;
for (var index in titles) {
var title = titles[index];
var titleVal = val[1].substring(textIndex, textIndex + title.length);
if (result) { result += ", "; data += ", "; }
textIndex += title.length + 2;
title = key + "/" + title;
size = Math.max(title.length, titleVal.length);
result += title + " ".repeat(size - title.length);
data += titleVal + " ".repeat(size - titleVal.length);
}
} else if (val.length === 1) {
size = Math.max(val[0].length, key.length);
if (result) { result += ", "; data += ", "; }
result += key + " ".repeat(size - key.length);
data += val[0] + " ".repeat(size - val[0].length);
}
}
return [result, data];
}
}
return [input];
}
Вот рабочий пример:
var object = {
"a": "1",
"b": "2",
"c":
{
"e": "3",
"f": "4",
"g": "5"
},
"d": "6"
};
function translateObject(input) {
if (typeof input === "object" && input !== null) {
if (input instanceof Array) {
var result = '"';
for (var index in input) {
if (index) result += ", ";
result += input[index];
}
return [result + '"'];
} else {
var data = "", result = "";
for (var key in input) {
if (key.includes(",")) {
throw new Error("Key cannot have a comma");
}
var val = translateObject(input[key]);
if (val.length === 2) {
var titles = val[0].split(", ");
var textIndex = 0;
var size = 0;
for (var index in titles) {
var title = titles[index];
var titleVal = val[1].substring(textIndex, textIndex + title.length);
if (result) { result += ", "; data += ", "; }
textIndex += title.length + 2;
title = key + "/" + title;
size = Math.max(title.length, titleVal.length);
result += title + " ".repeat(size - title.length);
data += titleVal + " ".repeat(size - titleVal.length);
}
} else if (val.length === 1) {
size = Math.max(val[0].length, key.length);
if (result) { result += ", "; data += ", "; }
result += key + " ".repeat(size - key.length);
data += val[0] + " ".repeat(size - val[0].length);
}
}
return [result, data];
}
}
return [input];
}
function objectToCsv(object) {
var result = translateObject(object);
return result[0] + "\n" + result[1];
}
var csv = objectToCsv(object);
document.querySelector("#console").innerText = csv;
console.log(csv);
#console {
font-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace;
white-space: pre;
}
span {
color: darkgrey;
}
<div id="console"></div>
<span>Names were minified to fit result in one line so that it is easier to read</span>
<span>Use this font family if you want all characters to have the same width</span>
font
и CSS properties
white-space
CSS properties
если вы хотите отобразить данные с использованием HTML
Вы можете проверить тип каждого значения и решить, что вы хотите сделать,
var data = require("./demo.json");
walk(obj){
for (var key in data){
if(type(data[key]) === "string"){
console.log(key + ':' + data[key]);
}
else if(Array.isArray(data[key])){
//its an array
}
else if(type(data[key]) === "object"){
//its an object
walk(data[key])
}
}
}
Причина, по которой ваша функция walk
рассылает вам D
или {
, потому что она проходит бесконечный цикл, когда она встречает строку,
function walk(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var val = obj[key];
console.log(val);
//here you need to check if it is an array or object, only then you should call walk
//calling walk on string would send it on a infinite loop
if(typeof(val) === "object"){
walk(val);
}
}
}
}
Возможно, то, что вы описываете, - это случай, когда один или несколько атрибутов ожидаемого объекта отсутствуют или не имеют содержимого (или членов, если это массив) и как создать код на этой основе.
Это не может быть абсолютно случайным, иначе вы не будете говорить о выходе csv style. Поэтому я предполагаю, что содержимое вашего объекта в основном там, но иногда вы найдете что-то не хватает.
Если бы это был я, я бы предварительно обработал объекты, загруженные при использовании JSON.parse() или любого эквивалента, который вы используете для преобразования строки в объекты javascript. Я бы использовал что-то вроде jquery $.extend, чтобы объединить идеально сформированный объект в мои данные и слияние массива, где target является атрибутом массива. Это даст мне согласованную модель данных для кодирования.
Итак, вы должны сделать данные так, как вы хотите, чтобы иметь возможность работать с ним без сюрпризов.
JSON.stringify
почемуJSON.stringify
недостаточно. Не могли бы вы добавить простой пример ввода и ожидаемого вывода для JSON?var data = require("./demo.json");
- Вы уже проанализировали это вdata
.