Sprawne przeformatowanie obiektu JSON

0

Chciałbym sprawnie – czytaj: łatwo i szybko – przeformatować obiekt JSON, zapisany w pliku tekstowym. Przykład – załóżmy, że obiekt wygląda tak:

{
    "A": [ { "B": "B1" }, ... ],
    "C": "D",
    "E": [ {
            "F": "G",
            "H": [ { "I": 1, "J": 2 }, ... ]
        },
        ...
    ]
}

I chciałbym przeformatować go na przykład tak:

{
    "A": [ { "B": { "I": 1, "J": 2 } }, ... ],
    "C": "D",
    "E": [ {
            "F": "G",
            "H": [ "B1", ... ]
        },
        ...
    ]
}

Jak widać, nie doszła żadna nowa treść, jedynie części wartości właściwości A oraz H uległy zamianie miejscami. I, powiedzmy, to byłaby jedyna zamiana w tym pliku, ale oczywiście – te wartości zmieniłyby się dla wielu elementów powyższych tablic. Gdyby wielokropki oznaczały maksymalnie nawet 5 elementów, to jeszcze można by to sformatować ręcznie. Ale jeśli mogą oznaczać 10 i 20 obiektów (tj. 10 * 20 elementów łącznie do wyszukania, zaznaczenia i zmiany miejscami, z prawdopodbieństwem pomyłki), to rozważam użycie np. skryptu. Obecnie jeszcze nie wiem, jak będę potrzebował pozamieniać wartości miejscami, będę musiał nad tym pomyśleć głębiej.

Pytanie: jak to zrobić, jakim językiem, może narzędziem? Może nie ma możliwości zrobienia tego szybciej niż ręcznie?

1

Nie wiem, co masz na myśli ręcznie. Ale powinno się dać napisać skrypt, który Ci skonwertuje obiekty. Co prawda, przy każdej zmianie, musiałaś byś taki skrypt pisać praktycznie od nowa.
Wydaje mi się, że nie ma żadnych uniwersalnych narzędzi do takich zadań specjalnych. Ale może się mylę.

Zamieszczam przykład w JS:

const objectInFile = { // twój przykładowy obiekt
    "A": [ { "B": "B1" }, { "B": "B2" } ],
    "C": "D",
    "E": [ {
            "F": "G",
            "H": [ { "I": 1, "J": 2 }, { "K": 3, "L": 4 }, 
                   { "M": 5, "N": 6} 
                 ]
        },
    ]
}

//funkcja która skonwertuje obiekt 
function convertObject(obj){
  const result = Object.assign({}, objectInFile);
  result.A = [];
  result.E = [];
  obj.E.forEach((value, i) => {
    const h = [];
    value.H.forEach((value, i) => {
      result.A.push({B: value});
      h.push("B"+ (i || ''));
    })
    result.E.push({F: "G", H:h});
  })
  
  return result;
}
const newObj = convertObject(objectInFile);
console.log(newObj);


//w wyniku dostaniemy taki obiekt
{
  "A": [
    { "B": { "I": 1, "J": 2 } },
    { "B": { "K": 3, "L": 4 } },
    { "B": { "M": 5, "N": 6 } }
  ],
  "C": "D",
  "E": [{ "F": "G", "H": ["B", "B1", "B2"] }]
}

https://jscomplete.com/playground/s267059

0

Może doprecyzuję, co już ustaliłem (aczkolwiek chyba nie ma sensu, bo coś czuję, że i tak nici z tego większej automatyzacji): najprawdopodobniej dane będą właśnie zamieniane miejscami między właściwościami/elementami o tych samych nazwach i poziomach. Czyli, na przykład, wartość właściwości X z poziomu zagnieżdżenia 3 zamienia miejsce z wartością właściwości Y z poziomu zagnieżdżenia 2, i tak co drugi element poziomu zagnieżdżenia 1, przez, powiedzmy, 50 poziomów.

PS. Właściwość X nazywa się tak samo – X – na każdym poziomie, podobnie właściwość Y.

0

Nie wnikałam specjalnie, więc może coś mi umyka, ale czy najprościej nie byłoby użyć standardowych funkcji?

  • JSON.parse - zrobić z tego jsona obiekt js,
  • przeprowadzić odpowiednie operacje na właściwościach stworzonego nią obiektu,
  • JSON.stringify - ze zmodyfikowanego obiektu wygenerować nowego jsona.
0

@Freja Draco: no zgadzam się, niemniej właśnie punkt nr 2 jest najbardziej problematyczny. :)

2
> jq -c . <in.json
{"A":[{"B":"B1"}],"C":"D","E":[{"F":"G","H":[{"I":1,"J":2}]}]}
> 
> jq -c '.A as $A | .A = .E[].H | .E[].H = $A' <in.json
{"A":[{"I":1,"J":2}],"C":"D","E":[{"F":"G","H":[{"B":"B1"}]}]}
> 

Możliwe, że da się to zrobić lepiej (parallel assignment?). Składnię jq zapominam po 5 minutach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1