Zachowaj kolejność kluczy JSON podczas konwersji JSON do CSV

82

Używam biblioteki JSON podanej tutaj http://www.json.org/java/index.html, aby przekonwertować ciąg json, który mam, na CSV. Ale problem jaki mam w tym, że kolejność kluczy gubi się po konwersji.

To jest kod konwersji:

    JSONObject jo = new JSONObject(someString);
    JSONArray ja = jo.getJSONArray("items");
    String s = CDL.toString(ja);
    System.out.println(s);

Oto zawartość „someString”:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
    ]
}

Oto wynik:

WO,QU,WR,QA,NO
hasd,asd,qwe,end,qwer

Podczas gdy to, czego oczekuję, to zachowanie kolejności kluczy:

WR,QU,QA,WO,NO
qwe,asd,end,hasd,qwer

Czy jest jakiś sposób, aby uzyskać ten wynik przy użyciu tej biblioteki? Jeśli nie, to czy istnieje inna biblioteka, która zapewni możliwość zachowania kolejności kluczy w wyniku?

Hery
źródło
4
Słowniki są nieposortowane. Nie sądzę, żeby JSON gwarantował porządek.
Falmarri
2
dzięki za informację. Ale nie mam innego wyboru, jak tylko użyć JSON w mojej aplikacji, a moja aplikacja musi zachować kolejność kluczy :(
Hery
W moim przypadku nie chodzi o brak porządku, ale o to, że jest on niedeterministyczny. Czasami dostaję klucz fooprzed kluczem, bara czasami barprzed foo. Utrudnia to pisanie testów.
Sridhar Sarnobat
Spotkałem się również z tą potrzebą, ale służy ona do szybkiego porównywania dzienników podczas testowania w czasie rzeczywistym. Muszę porównać nowo wygenerowane dzienniki z wcześniej wygenerowanymi dziennikami w czasie rzeczywistym dla aplikacji o dużej przepustowości. Można to zrobić na inne sposoby, ale wolałbym, aby dzienniki były w formacie JSON. Jednak aby zminimalizować użycie procesora, piszę własny moduł zapisujący JSON bezpośrednio do ciągu. W ogóle nie potrzebuję struktury wewnętrznej i mogę zachować kolejność kluczy w celu szybkiego porównywania ciągów logów. Istnieją dobre powody, aby chcieć przewidywalnego porządku.
Joe Lapp
napisz własny kod, aby przekonwertować JSON na konkretnie uporządkowany plik CSV, w ten sposób uszanujesz to, czym powinny być oba formaty.
Martijn Scheffer

Odpowiedzi:

95

Są (hackowe) sposoby, aby to zrobić ... ale nie powinieneś.

W JSON obiekt definiuje się następująco:

Obiekt to nieuporządkowany zestaw par nazwa / wartość.

Zobacz http://json.org .

Większość implementacji JSON nie stara się zachować kolejności par nazwa / wartość obiektu, ponieważ jest ona (z definicji) nieistotna.

Jeśli chcesz zachować porządek, musisz przedefiniować strukturę danych; na przykład

{
    "items":
    [
        [
            {"WR":"qwe"},
            {"QU":"asd"},
            {"QA":"end"},
            {"WO":"hasd"},
            {"NO":"qwer"}
        ],
    ]
}

lub prościej:

{
    "items":
    [
        {"WR":"qwe"},
        {"QU":"asd"},
        {"QA":"end"},
        {"WO":"hasd"},
        {"NO":"qwer"}
    ]
}

FOLLOWUP

Dzięki za informację, ale nie mam innego wyjścia, jak tylko użyć JSON w mojej aplikacji, a moja aplikacja musi zachować kolejność kluczy niezależnie od definicji obiektu JSON ... Nie mogę zmieniać formatu pliku JSON także...

Musisz przeprowadzić trudną rozmowę z kimkolwiek, kto zaprojektował tę strukturę plików i nie pozwoli ci jej zmienić. To jest / oni są po prostu błędne. Ci potrzeba , aby ich przekonać.

Jeśli naprawdę nie pozwolą ci tego zmienić:

  • Powinieneś nalegać, aby nie nazywać tego JSON ... bo tak nie jest.
  • Powinieneś zwrócić uwagę, że będziesz musiał napisać / zmodyfikować kod specjalnie do obsługi tego formatu "nie JSON" ... chyba że znajdziesz implementację JSON, która zachowuje kolejność. Jeśli są klientami płacącymi, upewnij się, że płacą za dodatkową pracę, którą musisz wykonać.
  • Należy zwrócić uwagę, że jeśli „nie JSON” musi być używane przez inne narzędzie, będzie to problematyczne. Rzeczywiście, ten problem będzie się powtarzał ...

Takie rzeczy są naprawdę złe. Z jednej strony Twoje oprogramowanie będzie naruszać dobrze ugruntowaną / długotrwałą specyfikację, której celem jest promowanie interoperacyjności. Z drugiej strony, głupcy, którzy zaprojektowali ten kiepski (nie JSON!) Format pliku, prawdopodobnie obrzucają systemy innych ludzi itp., Ponieważ systemy nie radzą sobie z ich bzdurami.

AKTUALIZACJA

Warto też przeczytać, co mówi na ten temat JSON RFC (RFC 7159) . Oto kilka fragmentów:

W latach od publikacji RFC 4627 JSON znalazł bardzo szerokie zastosowanie. Doświadczenie to ujawniło pewne wzorce, które, choć pozwalają na to specyfikacje, spowodowały problemy z interoperacyjnością.

JavaScript Object Notation (JSON) to format tekstowy służący do serializacji danych strukturalnych. ...

JSON może reprezentować cztery typy pierwotne (ciągi, liczby, wartości logiczne i null) oraz dwa typy strukturalne (obiekty i tablice).

Obiekt to nieuporządkowana kolekcja zawierająca zero lub więcej par nazwa / wartość, gdzie nazwa jest łańcuchem, a wartość jest ciągiem, liczbą, wartością logiczną, wartością null, obiektem lub tablicą.

Zaobserwowano, że biblioteki analizujące JSON różnią się pod względem tego, czy porządkowanie elementów składowych obiektów jest widoczne dla oprogramowania wywołującego. Implementacje, których zachowanie nie zależy od kolejności elementów, będą interoperacyjne w tym sensie, że te różnice nie będą miały na nie wpływu.

Stephen C.
źródło
3
@YogeshSomani - „rozwiązaniem” jest zdobycie odpowiedniej biblioteki JSON i „zhakowanie” jej tak, aby zachowała kolejność kluczy. Zobacz przykład odpowiedzi Gary'ego. Ale nie powinieneś oczekiwać, że zrobi to standardowa biblioteka JSON, ponieważ jest to ZŁY POMYSŁ, zachęcający do nadużywania specyfikacji JSON w ten sposób. Prawdziwym rozwiązaniem jest naprawienie aplikacji tak, aby poprawnie używała JSON.
Stephen C
10
wspaniale jest być najczystszym i absolutnym, ale nie oszukujmy się, istnieją rzeczywiste scenariusze, w których plik JSON wymaga zachowania kolejności zdefiniowanych wartości. Przekazywanie i akceptowanie ich w dowolnej kolejności jest podstawowym podejściem json, ale uważam to za inne niż możliwość pobrania dokumentu json i serializacji / deserializacji w równości. Często zdarza się, że trzeba wziąć dokument json i użyć go do utworzenia dokumentu innego standardowego WDDX, HTML itp., Gdzie kolejność musi zostać zachowana
Andrew Norman
3
@AndrewNorman - Gdyby to, co powiedziałeś o „potrzebie” było naprawdę prawdą, to specyfikacja powinna i byłaby zmieniona. Rzeczywistość jest taka, że ​​porządkowanie można łatwo przedstawić w inny sposób w JSON.
Stephen C
2
JSON wymaga jedynie, aby informacje nie były kodowane w kolejności kluczy; inaczej to nie jest JSON. Spójność serializacji to inny problem. W ramach jednej aplikacji spójność można zwykle zagwarantować przy użyciu wspólnej biblioteki JSON, ale istnieją wyjątki, na przykład gdy pojedyncze rozwiązanie obejmuje wiele platform lub struktur. W takich przypadkach albo musisz znaleźć sposób na poradzenie sobie z niekonsekwencją (wprowadzanie nieefektywności), albo znajdziesz sposób na zapewnienie spójności. Oba podejścia są prawidłowe.
Joe Lapp
2
„JSON wymaga tylko, aby informacje nie były kodowane w kolejności kluczy; inaczej nie jest to JSON”. . Myślę, że napisałeś to niepoprawnie. Prawidłowe stwierdzenie brzmi: „JSON nie wymaga, aby informacje były kodowane w kolejności kluczy”. Jest duża różnica między tymi dwoma stwierdzeniami…
Stephen C
47

Utrzymanie porządku jest dość proste. Miałem ten sam problem z utrzymaniem kolejności z warstwy DB do warstwy interfejsu użytkownika.

Otwórz plik JSONObject.java. Wewnętrznie używa HashMap, który nie utrzymuje kolejności.

Zmień to na LinkedHashMap:

    //this.map = new HashMap();
    this.map = new LinkedHashMap();

To zadziałało dla mnie. Dajcie znać w komentarzach. Sugeruję, że sama biblioteka JSON powinna mieć inną klasę JSONObject, która utrzymuje porządek, jak JSONOrderdObject.java. Jestem bardzo ubogi w wyborze nazwisk.

Gary
źródło
2
svn checkout json-simple. zmodyfikuj plik org.json.simple.JSONObject, <code> JOSNObject rozszerza LinkedHashMap ... </code> z <code> .. HashMap .. </code>, napraw import i działa dla mnie. v1.1.1.
Marku
2
To świetne rozwiązanie w jednym wierszu, którego nigdy bym nie pomyślał. Działa doskonale i nie musiałem zmieniać żadnego innego mojego kodu. +1
DaaaahWhoosh
Świetna poprawka. Jesteś bohaterem Sir
Gregory Nowakowski
nie działa, dodałem import, zmieniłem go tak, jak powiedziałeś, nawet próbowałem to zrobić w ten sposób: this.map = new LinkedHashMap<String, Object>();nadal nie działa. Proszę pomóż ?
Tarek
4
Haha naprawdę? Modyfikowanie biblioteki JSON do swoich potrzeb? Mogę sobie tylko wyobrazić, że dzieje się to w firmowych bazach wiedzy. „Wykonaj czystą instalację mvn, pobierz jar, znajdź go, zdekompiluj, a następnie zamień HashMap na LinkedHashMap”. To będzie działać świetnie dla wielu zespołów programistów (nie).
Chris Neve,
23

JSONObject.javabierze podaną mapę. Może być LinkedHashMaplub TreeMapi zajmie to hashmaptylko wtedy, gdy mapa jest pusta.

Oto konstruktor JSONObject.javaklasy, który będzie sprawdzał mapę.

 public JSONObject(Map paramMap)
  {
    this.map = (paramMap == null ? new HashMap() : paramMap);
  }

Więc przed utworzeniem konstrukcji obiektu json LinkedHashMapi przekazaniem jej do konstruktora w ten sposób,

LinkedHashMap<String, String> jsonOrderedMap = new LinkedHashMap<String, String>();

jsonOrderedMap.put("1","red");
jsonOrderedMap.put("2","blue");
jsonOrderedMap.put("3","green");

JSONObject orderedJson = new JSONObject(jsonOrderedMap);

JSONArray jsonArray = new JSONArray(Arrays.asList(orderedJson));

System.out.println("Ordered JSON Fianl CSV :: "+CDL.toString(jsonArray));

Nie ma więc potrzeby zmiany JSONObject.javaklasy. Mam nadzieję, że to komuś pomoże.

Deepak Nagaraj
źródło
3
Dobra odpowiedź, działa na normalnej Javie, ale nie działa na Androidzie. Sprawdzam org.json.JSONObject w androidzie, szkoda, że ​​android nadal używa hashmap stworzonego wewnętrznie. Kopiuje tylko pary nazwa / wartość z paramMap do HashMap ... :(
正宗 白 布鞋
Zamówiłem JsonObject, ale kiedy próbuję dodać ten obiekt do JsonArray, otrzymuję nieuporządkowany. Muszę umieścić obiekt w tablicy, potrzebuję obiektów tablicy, a następnie umieszczam nagłówek w tablicy i odsyła. Np .: jeden obiekt; {CUSTOMER_SECTOR_ID = 611, CUSTOMER_NO = 0000003204, CUSTOMER_NAME = MARMARİS - KARAS GIDA KARAS TÜKETİM MADDELERİ GIDA LOJ.} Otrzymuję to, jeśli umieszczę dwa obiekty w tablicy: [{"CUSTOMER_NAME": "SILA GIDA_NADA": "SILA GIDAER_NAME": " 0000003122 "," CUSTOMER_SECTOR_ID ":" 611 "}, {" CUSTOMER_NAME ":" M ":" 0013114714 "," CUSTOMER_SECTOR_ID ":" 611 "}] Jak widzisz, jest źle. Jak mogę to naprawić
Sahin Yanlık
2
@Deepak Nagaraj. Wypróbowałem twoje rozwiązanie, ale nie zadziałało, JSONObjectnie jest zamówione jako moje LinkedHashMap. Czy korzystasz z org.jsonlib?
Ismail Sen,
1
To nie jest ten org.jsonjedyny. Definiuje HashMapwewnętrznie, cokolwiek mu Mapdasz: @Deepak Czy możesz wskazać nam implementację, z której korzystałeś?
Campa,
8
To nie zadziała z org.jsonbiblioteką. Kiedy konstruujesz nowy JSONObjectobiekt, przekazując mapę jako argument, zawsze zostanie on przekonwertowany na plik HashMap. Konstruktor najpierw tworzy nową mapę:, this.map = new HashMap<String, Object>();a następnie wykonuje pętlę nad twoją mapą, kopiując każdy element do swojego HashMap.
itachi
13

Bardziej rozwlekłym, ale szeroko stosowanym rozwiązaniem tego rodzaju problemu jest użycie pary struktur danych: listy zawierającej uporządkowanie i mapy zawierającej relacje.

Na przykład:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
    ],
    "itemOrder":
        ["WR", "QU", "QA", "WO", "NO"]
}

Iterujesz listę itemOrder i używasz ich do wyszukiwania wartości mapy. Porządkowanie jest zachowane, bez kłopotów.

Wielokrotnie korzystałem z tej metody.

Spodnie Robotic
źródło
Staje się to skomplikowane, jeśli twoja mapa nie jest tylko prostymi parami klucz-wartość ...
zfj3ub94rf576hc4eegm
10

Kolejne hackerskie rozwiązanie wykorzystujące Reflect:

JSONObject json = new JSONObject();
Field map = json.getClass().getDeclaredField("map");
map.setAccessible(true);//because the field is private final...
map.set(json, new LinkedHashMap<>());
map.setAccessible(false);//return flag
fabe
źródło
1
Nie dostałem twojej odpowiedzi
M. Usman Khan
1
Sztuczka polega na wewnętrznej modyfikacji klasy, aby używała LinkedHashMap zamiast domyślnej HashMap, dzięki czemu obiekt JSON ma dane w kolejności, w jakiej je umieściłeś, nie jest to bezpośrednio sortowane, ale zadziałało, ponieważ przeanalizowane dane są już posortowane .
fabe
wygląda dobrze, ale jak parsować Json String PO map.set (json, new LinkedHashMap <> ()); ponieważ Json String jest przekazywany w konstruktorze, prawda? na przykład nowy JSONObject (jsonString).
M. Usman Khan
To też nie zadziałało. nie ma pola „map”, istnieje pole „nameValuePairs”, które jest już LinckedHashMap i nadal nie działa.
M. Usman Khan
1
Jakiej implementacji JSONObject używasz? Używam org.json w wersji 20140107 i musiałem zachować kolejność i tak to zadziałało.
fabe
6

Apache Wink zamówiłJSONObject . Zachowuje kolejność podczas analizowania ciągu.

Kirill Rakhman
źródło
4

Właśnie natknąłem się na ten sam problem, uważam, że ostateczne rozwiązanie zastosowane przez autora polegało na użyciu niestandardowego ContainerFactory:

public static Values parseJSONToMap(String msgData) {
    JSONParser parser = new JSONParser();
    ContainerFactory containerFactory = new ContainerFactory(){
        @Override
        public Map createObjectContainer() {
            return new LinkedHashMap();
        }

        @Override
        public List creatArrayContainer() {
            return null;
        }
    };
    try {
        return (Map<String,Object>)parser.parse(msgData, containerFactory);
    } catch (ParseException e) {
        log.warn("Exception parsing JSON string {}", msgData, e);
    }
    return null;
}  

patrz http://juliusdavies.ca/json-simple-1.1.1-javadocs/org/json/simple/parser/JSONParser.html#parse(java.io.Reader,org.json.simple.parser.ContainerFactory)

Rafael
źródło
naprawdę bardzo dobre i praktyczne rozwiązanie. Co powiesz na napisanie metody lokalnej anonimowej klasy wewnętrznej dla containerFactory?
Shailesh Saxena
3

Rozwiązany.

Użyłem biblioteki JSON.simple stąd https://code.google.com/p/json-simple/, aby przeczytać ciąg JSON, aby zachować kolejność kluczy i użyć biblioteki JavaCSV stąd http://sourceforge.net/ projekty / javacsv / do konwersji do formatu CSV.

Hery
źródło
Dziwię się, że to zadziałało. Zgodnie z moim odczytaniem zarówno kodu, jak i komentarzy klasy JSONObject ( code.google.com/p/json-simple/source/browse/trunk/src/main/java/... ) nie robi nic, aby zachować kolejność kluczy.
Stephen C
1
Nie opisałem tutaj pełnego rozwiązania, ale sednem tego jest to, że json-simple zapewnia fabrykę, za pomocą której można określić strukturę danych używaną do przechowywania obiektów json. Po prostu określ, aby użyć LinkedHashMap.
Hery
@ Hery, mam ten sam problem, ale nie mogłem go rozwiązać. Używam org.jsonkonwersji List<LinkedHahMap>do JSONArray, aby utworzyć plik CSV, CSVjest tworzony, ale nie w tej samej kolejności, co mój List . Próbowałem użyć dwóch bibliotek, które tu przedstawiłeś, ale nie mogłem znaleźć metod konwersji na. CSVCzy mógłbyś podać więcej szczegółów.
Ismail Sen,
2

Wiem, że to zostało rozwiązane i pytanie zostało zadane dawno temu, ale ponieważ mam do czynienia z podobnym problemem, chciałbym przedstawić zupełnie inne podejście do tego:

W przypadku tablic mówi: „Tablica to uporządkowany zbiór wartości”. na http://www.json.org/ - ale obiekty („Obiekt jest nieuporządkowanym zbiorem par nazwa / wartość”) nie są uporządkowane.

Zastanawiam się, dlaczego ten obiekt jest w tablicy - to sugeruje, że nie ma takiego porządku.

{
"items":
[
    {
        "WR":"qwe",
        "QU":"asd",
        "QA":"end",
        "WO":"hasd",
        "NO":"qwer"
    },
]
}

Zatem rozwiązaniem byłoby umieszczenie kluczy w „prawdziwej” tablicy i dodanie danych jako obiektów do każdego klucza, w następujący sposób:

{
"items":
[
    {"WR": {"data": "qwe"}},
    {"QU": {"data": "asd"}},
    {"QA": {"data": "end"}},
    {"WO": {"data": "hasd"}},
    {"NO": {"data": "qwer"}}
]
}

Jest to więc podejście, które próbuje ponownie przemyśleć oryginalny model i jego założenia. Ale nie testowałem (i zastanawiam się), czy wszystkie zaangażowane narzędzia zachowałyby kolejność tej oryginalnej tablicy JSON.

cslotty
źródło
1
to nie pozwala mi na sprawdzenie klucza.
mickeymoon
Więc czego chcesz - haszysz czy coś zamówionego !? Jeśli chcesz połączyć obie, stwórz obie i zindeksuj jedną z tych struktur ... w przeciwnym razie wydaje się to być bardziej problemem projektowym lub mieszaniem zainteresowań.
cslotty
1
nie chodzi o mieszanie zainteresowań, jest to dość prawdopodobny przypadek użycia, który w językach takich jak Java jest obsługiwany przez konstrukcje takie jak LinkedHashMap, uporządkowana mapa, która zachowuje kolejność wstawiania. W takim razie czego chcę, chcę, aby oboje mogli iterować na klawiszach w określonej kolejności i szybko je wyszukiwać. Myślę, że odpowiedź @Robotic Pants działałaby prawie, chociaż jest trochę hakerska.
mickeymoon
To prawda, mickeymoon, właśnie miałem to powiedzieć! Ale w JSON to nie istnieje, prawda? Wtedy musiałbyś zaangażować języki / mechanizmy, które zapewniają Ci coś takiego.
cslotty
1

W prawdziwym świecie aplikacja prawie zawsze będzie miała komponent bean Java lub domenę, która ma być serializowana / deserializowana do / z formatu JSON. Jak już wspomniano, specyfikacja obiektu JSON nie gwarantuje porządku, a wszelkie manipulacje przy tym zachowaniu nie uzasadniają tego wymagania. W mojej aplikacji miałem ten sam scenariusz, w którym musiałem zachować porządek tylko ze względu na worek czytelności. Użyłem standardowego sposobu Jacksona, aby serializować moje ziarno Java do JSON:

Object object = getObject();  //the source java bean that needs conversion
String jsonString = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(object);

Aby utworzyć json z uporządkowanym zestawem elementów, po prostu używam adnotacji właściwości JSON w komponencie bean Java, którego użyłem do konwersji. Przykład poniżej:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"name","phone","city","id"})
public class SampleBean implements Serializable {
    private int id;
    private String name:
    private String city;
    private String phone;

    //...standard getters and setters
}

zastosowana powyżej getObject ():

public SampleBean getObject(){
    SampleBean bean  = new SampleBean();
    bean.setId("100");
    bean.setName("SomeName");
    bean.setCity("SomeCity");
    bean.setPhone("1234567890");
    return bean;
}

Dane wyjściowe są wyświetlane zgodnie z adnotacją kolejności właściwości Json:

{
    name: "SomeName",
    phone: "1234567890",
    city: "SomeCity",
    id: 100
}
Vishal
źródło
0

Najbezpieczniejszym sposobem jest prawdopodobnie nadpisywanie kluczy, które są używane do generowania danych wyjściowych:

new JSONObject(){
  @Override
  public Iterator keys(){
    TreeSet<Object> sortedKeys = new TreeSet<Object>();
    Iterator keys = super.keys();
    while(keys.hasNext()){
      sortedKeys.add(keys.next());
    }
    return sortedKeys.iterator();
  }
};
Kardigen
źródło
1
To nie rozwiązuje podanego problemu. Powoduje sortowanie kluczy ... ale pytanie prosi o zachowanie kolejności wstawiania.
Stephen C
0

patchFor (answer @gary):

$ git diff JSONObject.java                                                         
diff --git a/JSONObject.java b/JSONObject.java
index e28c9cd..e12b7a0 100755
--- a/JSONObject.java
+++ b/JSONObject.java
@@ -32,7 +32,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.Enumeration;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
@@ -152,7 +152,9 @@ public class JSONObject {
      * Construct an empty JSONObject.
      */
     public JSONObject() {
-        this.map = new HashMap<String, Object>();
+//      this.map = new HashMap<String, Object>();
+        // I want to keep order of the given data:
+        this.map = new LinkedHashMap<String, Object>();
     }

     /**
@@ -243,7 +245,7 @@ public class JSONObject {
      * @throws JSONException
      */
     public JSONObject(Map<String, Object> map) {
-        this.map = new HashMap<String, Object>();
+        this.map = new LinkedHashMap<String, Object>();
         if (map != null) {
             Iterator<Entry<String, Object>> i = map.entrySet().iterator();
             while (i.hasNext()) {
Campa
źródło
0

Możesz użyć następującego kodu, aby wykonać niestandardową serializację ZAMÓWIONĄ i deserializację tablicy JSON (w tym przykładzie założono, że zamawiasz ciągi, ale można go zastosować do wszystkich typów):

Serializacja

JSONArray params = new JSONArray();
int paramIndex = 0;

for (String currParam : mParams)
{
    JSONObject paramObject = new JSONObject();
    paramObject.put("index", paramIndex);
    paramObject.put("value", currParam);

    params.put(paramObject);
    ++paramIndex;
}

json.put("orderedArray", params);

Deserializacja

JSONArray paramsJsonArray = json.optJSONArray("orderedArray");
if (null != paramsJsonArray)
{
    ArrayList<String> paramsArr = new ArrayList<>();
    for (int i = 0; i < paramsJsonArray.length(); i++)
    {
        JSONObject param = paramsJsonArray.optJSONObject(i);
        if (null != param)
        {
            int paramIndex = param.optInt("index", -1);
            String paramValue = param.optString("value", null);

            if (paramIndex > -1 && null != paramValue)
            {
                paramsArr.add(paramIndex, paramValue);
            }
        }
    }
}
Muzikant
źródło
0

Twój przykład:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
        ...
    ]
}

dodaj element „itemorder”

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
        ...
    ],
    "itemorder":["WR","QU","QA","WO","NO"]
}

Ten kod generuje żądane dane wyjściowe bez wiersza tytułu kolumny:

JSONObject output = new JSONObject(json);
JSONArray docs = output.getJSONArray("data");
JSONArray names = output.getJSONArray("itemOrder");
String csv = CDL.toString(names,docs);
Adriano
źródło
To usunęło nagłówek CSV, teraz mam uporządkowane wiersze, ale bez nagłówka
Pedro Joaquín
0

zamiast używać jsonObject spróbuj użyć CsvSchema w ten sposób łatwiej i bezpośrednio konwertuje obiekt na csv

CsvSchema schema = csvMapper.schemaFor(MyClass.class).withHeader();
        csvMapper.writer(schema).writeValueAsString(myClassList);

i mentains id zamówić pojo ma @JsonPropertyOrder w nim

rahul
źródło
0

Underscore-java zachowuje zamówienia na elementy podczas odczytu json. Jestem opiekunem projektu.

String json = "{\n"
      + "    \"items\":\n"
      + "    [\n"
      + "        {\n"
      + "            \"WR\":\"qwe\",\n"
      + "            \"QU\":\"asd\",\n"
      + "            \"QA\":\"end\",\n"
      + "            \"WO\":\"hasd\",\n"
      + "            \"NO\":\"qwer\"\n"
      + "        }\n"
      + "    ]\n"
      + "}";
System.out.println(U.fromJson(json));

// {items=[{WR=qwe, QU=asd, QA=end, WO=hasd, NO=qwer}]}
Valentyn Kolesnikov
źródło
-1

Przetestowałem rozwiązanie mrugnięcia i działa dobrze:

@Test
public void testJSONObject() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("bbb", "xxx");
    jsonObject.put("ccc", "xxx");
    jsonObject.put("aaa", "xxx");
    jsonObject.put("xxx", "xxx");
    System.out.println(jsonObject.toString());
    assertTrue(jsonObject.toString().startsWith("{\"xxx\":"));
}

@Test
public void testWinkJSONObject() throws JSONException {
    org.apache.wink.json4j.JSONObject jsonObject = new OrderedJSONObject();
    jsonObject.put("bbb", "xxx");
    jsonObject.put("ccc", "xxx");
    jsonObject.put("aaa", "xxx");
    jsonObject.put("xxx", "xxx");
    assertEquals("{\"bbb\":\"xxx\",\"ccc\":\"xxx\",\"aaa\":\"xxx\",\"xxx\":\"xxx\"}", jsonObject.toString());
}
jgpelaez
źródło
Zależność Maven: <dependency> <groupId> org.apache.wink </groupId> <artifactId> wink-json4j </artifactId> <version> 1.4 </version> </dependency>
jgpelaez
Ta sama odpowiedź co @cypressious ... opublikowana 2 lata wcześniej. A przykład nie dodaje żadnej wartości.
Stephen C