Chociaż jestem w stanie prawidłowo przeanalizować tę ładunek, jeśli określam klucze za pomocą notacji wspornika, jak można analizować go dynamicznie?

{
    "name": "Demo User",
    "birthday": "January 1st",
    "hobbies": 
        {
        "morning": "coding",
        "afternoon": "kewl kids stuff",
        "nighttime": "random"
    },
    "date": "June 25th"
}

To, co mam na myśli, że hobby mogą nie być tam, ani inne pole, takie jak "ulubione pokarmy", może być tablicą lub obiekt.

Ten scenariusz spowodował, że wiele frustracji w ciągu ostatnich kilku miesięcy i próbuję zobaczyć, czy ktoś może mi wyjaśnić, jak pomyślnie analizować go, dynamicznie.

Znalazłem podejście rekurencyjne "spacer", które nie jest już błędne, ale powraca pierwszą rzeczą, jaką przychodzi na każdą iterację.

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

Podstawowe na tym, co znalazłem, dane są importowane jako JSON, a jeśli ją rozrusza, staje się ciągiem (oczywiście).

Domyślnie

{ name: 'Demo User',
  birthday: 'January 1st',
  hobbies:
   { morning: 'coding',
     afternoon: 'kewl kids stuff',
     nighttime: 'random' },
  date: 'June 25th' }

sminify

{"name":"Demo User","birthday":"January 1st","hobbies":{"morning":"coding","afternoon":"kewl kids stuff","nighttime":"random"},"date":"June 25th"}

Oba są podobne, ale jedyną różnicą na wyjściu jest spamowanie D x razy (będąc pierwszą wartością, myślę?) Lub spamowanie {x1}} x razy (będąc pierwszą wartością łańcucha?

Próbowałem znacznie bardziej podstawowego podejścia

var data = require("./demo.json");

for (var key in data){
    console.log(key + ':' + data[key]);
}

Który działa dobrze, ale zgodnie z oczekiwaniami, hobby powracają [object Object], ponieważ nie jest to imię. Mogę przejść przez hobbies, ale znowu - nie wiem, czy będzie to istnieć.

Witamy wszelkie dane wejściowe - ogólne pytanie, ale proces, który spowodował, że wiele frustracji na różnych projektach w ciągu ostatnich kilku miesięcy.

AKTUALIZACJA

Moja niejasność powoduje słusznie - tak zamieszanie.

Powiedzmy, że mój cel jest przekształcenie tego JSON ładunku w CSV. Potrzebuję każdego klucza dla nagłówków, a każda wartość jest rzędem pod powiedziałym nagłówkiem. Moim problemem jest, jak i iteruje go, skończyłem prawidłowo z obiektami najwyższego poziomu. Następnie skończyłem kolumnę obiektową obiekt bez danych.

Aby uzyskać dokładny przykład, powiedzmy, że moim celem jest przekonwertowanie JSON

name, birthday, hobbies/morning, hobbies/afternoon, hobbies/nighttime, data
Demo User, January 1st, coding, kewl kids stuff, random, June 25th

Aktualizacja nr 2

Dodatkowy wariant array.

Oczekiwałbym

{
...
    "hobbies": 
        {
        "morning": "coding",
        "afternoon": "kewl kids stuff",
        "nighttime": "random"
    },
    ...
}

Do wyjścia hobbies/morning, hobbies/afternoon, hobbies/nighttimes

Oczekiwałbym

{
...
    "hobbies": ["coding", "kewl kids stuff", "coding"]
    ...
}

Aby wyprowadzić jedną kolumnę hobbies z przedmiotami zamkniętymi cytatami "coding, kewl kids stuff, coding"

2
DNorthrup 25 czerwiec 2017, 20:16

3 odpowiedzi

Najlepsza odpowiedź

Spróbuj użyć tej funkcji (fragment na końcu odpowiedzi)

/**
 * 
 * @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];
}

Oto działający przykład:

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>
1
nick zoum 25 czerwiec 2017, 19:06

Być może, co opisujesz, jest przypadkiem, w którym można się spodziewać jednego lub więcej atrybutów obiektu, nie jest obecny lub nie ma treści (ani członków, jeśli jest to tablica), a jak zbudować kod na tej podstawie.

Nie może być całkowicie przypadkowy, w przeciwnym razie nie mówiłbyś o wyjściu w stylu CSV. Załóż więc, że zawartość obiektu jest głównie tam, ale czasami znajdziesz coś brakującego.

Gdyby był mną, wstępnie przetwarzam załadowane obiekty podczas korzystania z JSON.PARSE () lub dowolnego odpowiednika, którego używasz do konwersji ciągu do obiektów JavaScript. Użyłbym czegoś takiego jak jQuery's $ .extend, aby połączyć idealnie utworzony obiekt do moich danych, i Łączenie tablicy gdzie cel jest atrybutem tablicy. Dałoby mi to spójny model danych do kodu przeciwko.

Podsumowując - musisz dokonać danych tak, jak chcesz, aby być w stanie z nim pracować bez niespodzianek.

0
Vanquished Wombat 25 czerwiec 2017, 18:10

Możesz sprawdzić typ każdej wartości i zdecydować, co chcesz zrobić,

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])       
        }
    }
}

Powód funkcji walk jest spamowanie Cię z D lub { jest dlatego, że jest to w nieskończonej pętli, gdy spogląda ciąg,

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);
      }
    }
  }
}
2
Anurag Awasthi 25 czerwiec 2017, 18:19