Получить значения из JSON Parse Object в Object; Динамические ключи (JavaScript)

1

Хотя я могу правильно разобрать эту полезную нагрузку, если я укажу ключи через нотацию с помощью скобок, как бы вы могли разобрать ее динамически?

{
    "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"

  • 2
    Все еще не JSON.stringify почему JSON.stringify недостаточно. Не могли бы вы добавить простой пример ввода и ожидаемого вывода для JSON?
  • 0
    var data = require("./demo.json"); - Вы уже проанализировали это в data .
Показать ещё 5 комментариев
Теги:
object
arrays

3 ответа

1
Лучший ответ

Попробуйте использовать эту функцию (фрагмент в конце ответа)

/**
 * 
 * @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>
  • 0
    Вау, это потребовало гораздо большего, чем я ожидал. Я ценю ваши усилия! Я отмечу это как принятый, и перепроектирую это, чтобы полностью понять Я думаю, что я понимаю основную концепцию этого.
  • 0
    @DNorthrup Пожалуйста, дайте мне знать, если есть что-то, что вы не понимаете, а также убедитесь, что вы используете этот font и CSS properties white-space CSS properties если вы хотите отобразить данные с использованием HTML
1

Вы можете проверить тип каждого значения и решить, что вы хотите сделать,

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);
      }
    }
  }
}
0

Возможно, то, что вы описываете, - это случай, когда один или несколько атрибутов ожидаемого объекта отсутствуют или не имеют содержимого (или членов, если это массив) и как создать код на этой основе.

Это не может быть абсолютно случайным, иначе вы не будете говорить о выходе csv style. Поэтому я предполагаю, что содержимое вашего объекта в основном там, но иногда вы найдете что-то не хватает.

Если бы это был я, я бы предварительно обработал объекты, загруженные при использовании JSON.parse() или любого эквивалента, который вы используете для преобразования строки в объекты javascript. Я бы использовал что-то вроде jquery $.extend, чтобы объединить идеально сформированный объект в мои данные и слияние массива, где target является атрибутом массива. Это даст мне согласованную модель данных для кодирования.

Итак, вы должны сделать данные так, как вы хотите, чтобы иметь возможность работать с ним без сюрпризов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню