Behalten Sie die Reihenfolge der JSON-Schlüssel während der JSON-Konvertierung in CSV bei

82

Ich verwende die hier bereitgestellte JSON-Bibliothek http://www.json.org/java/index.html , um eine JSON- Zeichenfolge, die ich habe, in CSV zu konvertieren. Das Problem ist jedoch, dass die Reihenfolge der Schlüssel nach der Konvertierung verloren geht.

Dies ist der Konvertierungscode:

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

Dies ist der Inhalt von "someString":

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

Das ist das Ergebnis:

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

Ich erwarte zwar, dass die Reihenfolge der Schlüssel eingehalten wird:

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

Gibt es eine Möglichkeit, dieses Ergebnis mit dieser Bibliothek zu erzielen? Wenn nicht, gibt es eine andere Bibliothek, die die Möglichkeit bietet, die Reihenfolge der Schlüssel im Ergebnis beizubehalten?

Hery
quelle
4
Wörterbücher sind unsortiert. Ich glaube nicht einmal, dass JSON Ordnung garantiert.
Falmarri
2
Danke für die Information. Aber ich habe keine andere Wahl, als JSON in meiner Anwendung zu verwenden, und meine Anwendung muss die Reihenfolge der Schlüssel beibehalten :(
Hery
In meinem Fall geht es nicht um das Fehlen einer Ordnung, sondern darum, dass sie nicht deterministisch ist. Manchmal bekomme ich Schlüssel foovor Schlüssel barund manchmal barvorher foo. Dies macht es schwierig, Tests für zu schreiben.
Sridhar Sarnobat
Ich bin auch auf dieses Bedürfnis gestoßen, aber es dient dem schnellen Protokollvergleich während Echtzeit-Tests. Ich muss neu generierte Protokolle in Echtzeit mit zuvor generierten Protokollen vergleichen, um eine Anwendung mit hohem Durchsatz zu erhalten. Es gibt andere Möglichkeiten, dies zu tun, aber ich würde es vorziehen, wenn die Protokolle im JSON-Format vorliegen. Um die CPU-Auslastung zu minimieren, schreibe ich jedoch meinen eigenen Direct-to-String-JSON-Writer. Ich brauche die interne Struktur überhaupt nicht und kann die Schlüsselreihenfolge für schnelle Zeichenfolgenvergleiche von Protokollen beibehalten. Es gibt gute Gründe, eine vorhersehbare Reihenfolge zu wollen.
Joe Lapp
Schreiben Sie Ihren eigenen Code, um JSON in eine speziell geordnete CSV-Datei zu konvertieren. Auf diese Weise respektieren Sie, was beide Formate sein sollen.
Martijn Scheffer

Antworten:

95

Es gibt (hackige) Möglichkeiten, dies zu tun ... aber Sie sollten es nicht tun.

In JSON wird ein Objekt folgendermaßen definiert:

Ein Objekt ist eine ungeordnete Menge von Name / Wert-Paaren.

Siehe http://json.org .

Die meisten Implementierungen von JSON bemühen sich nicht, die Reihenfolge der Name / Wert-Paare eines Objekts beizubehalten, da sie (per Definition) nicht signifikant ist.

Wenn Sie möchten, dass die Ordnung erhalten bleibt, müssen Sie Ihre Datenstruktur neu definieren. z.B

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

oder einfacher:

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

NACHVERFOLGEN

Vielen Dank für die Informationen, aber ich habe keine andere Wahl, als JSON in meiner Anwendung zu verwenden, und meine Anwendung muss die Reihenfolge der Schlüssel unabhängig von der Definition des JSON-Objekts beibehalten ... Ich darf das Format der JSON-Datei nicht ändern auch...

Sie müssen ein hartes Gespräch mit demjenigen führen, der diese Dateistruktur entworfen hat, und Sie dürfen sie nicht ändern. Es ist / sie sind einfach falsch. Sie müssen sie überzeugen.

Wenn sie dich das wirklich nicht ändern lassen:

  • Sie sollten darauf bestehen , nicht es JSON Aufruf ... ‚cos es nicht ist.
  • Sie sollten darauf hinweisen, dass Sie Code speziell schreiben / ändern müssen, um dieses "Nicht-JSON" -Format zu verarbeiten ... es sei denn, Sie finden eine JSON-Implementierung, die die Reihenfolge beibehält. Wenn sie zahlende Kunden sind, stellen Sie sicher, dass sie für diese zusätzliche Arbeit bezahlen, die Sie erledigen müssen.
  • Sie sollten darauf hinweisen, dass es problematisch sein wird, wenn "nicht JSON" von einem anderen Tool verwendet werden muss. In der Tat wird dieses Problem immer und immer wieder auftreten ...

So etwas ist wirklich schlimm. Einerseits verstößt Ihre Software gegen eine etablierte / langjährige Spezifikation, die die Interoperabilität fördern soll. Auf der anderen Seite verschmutzen die Trottel, die dieses lahme (nicht JSON!) Dateiformat entworfen haben, wahrscheinlich die Systeme anderer Leute usw., weil die Systeme ihren Unsinn nicht bewältigen können .

AKTUALISIEREN

Es lohnt sich auch zu lesen, was der JSON RFC (RFC 7159) zu diesem Thema sagt. Hier einige Auszüge:

In den Jahren seit der Veröffentlichung von RFC 4627 hat JSON eine sehr breite Verwendung gefunden. Diese Erfahrung hat bestimmte Muster aufgedeckt, die, obwohl sie nach ihren Spezifikationen zulässig sind, Interoperabilitätsprobleme verursacht haben.

JavaScript Object Notation (JSON) ist ein Textformat für die Serialisierung strukturierter Daten. ...

JSON kann vier primitive Typen (Zeichenfolgen, Zahlen, Boolesche Werte und Null) und zwei strukturierte Typen (Objekte und Arrays) darstellen.

Ein Objekt ist eine ungeordnete Sammlung von null oder mehr Name / Wert-Paaren, wobei ein Name eine Zeichenfolge und ein Wert eine Zeichenfolge, eine Zahl, ein Boolescher Wert, eine Null, ein Objekt oder ein Array ist.

Es wurde beobachtet, dass JSON-Parsing-Bibliotheken sich darin unterscheiden, ob sie die Reihenfolge der Objektmitglieder für aufrufende Software sichtbar machen oder nicht. Implementierungen, deren Verhalten nicht von der Reihenfolge der Mitglieder abhängt, sind in dem Sinne interoperabel, dass sie von diesen Unterschieden nicht betroffen sind.

Stephen C.
quelle
6
@Hery - Rechnung sie :-)
Stephen C
3
@YogeshSomani - Die "Lösung" besteht darin, eine ordnungsgemäße JSON-Bibliothek zu beschaffen und sie zu "hacken", damit die Schlüsselreihenfolge erhalten bleibt. Ein Beispiel finden Sie in Garys Antwort. Sie sollten jedoch nicht erwarten, dass eine Standard-JSON-Bibliothek dies tut, da dies eine SCHLECHTE IDEE ist, um den Missbrauch der JSON-Spezifikation wie dieser zu fördern. Die eigentliche Lösung besteht darin, Ihre Anwendung so zu reparieren, dass JSON ordnungsgemäß verwendet wird.
Stephen C
10
Es ist großartig, rein und absolut zu sein, aber machen wir uns nichts vor. Es gibt reale Szenarien, in denen eine JSON-Datei die Reihenfolge ihrer definierten Werte beibehalten muss. Sie in beliebiger Reihenfolge zu bestehen und zu akzeptieren, ist ein grundlegender json-Ansatz, aber ich halte dies für anders als die Fähigkeit, ein json-Dokument zu nehmen und in Gleichheit zu serialisieren / deserialisieren. Es ist ein häufiger Anwendungsfall, ein JSON-Dokument zu verwenden, um ein Dokument aus einem anderen Standard-WDDX, HTML usw. zu erstellen, in dem die Reihenfolge beibehalten werden muss
Andrew Norman,
3
@ AndrewNorman - Wenn das, was Sie über "Bedürfnis" gesagt haben, wirklich wahr wäre, dann sollte und wäre die Spezifikation geändert worden. Die Realität ist, dass es einfach ist, die Bestellung in JSON auf andere Weise darzustellen.
Stephen C
2
JSON erfordert nur, dass Informationen nicht in der Reihenfolge der Schlüssel codiert werden. Sonst ist es nicht JSON. Die Konsistenz der Serialisierung ist ein anderes Problem. Innerhalb einer einzelnen App kann die Konsistenz normalerweise durch die Verwendung einer gemeinsamen JSON-Bibliothek gewährleistet werden. Es gibt jedoch Ausnahmen, z. B. wenn eine einzelne Lösung mehrere Plattformen oder Frameworks umfasst. In diesen Fällen müssen Sie entweder einen Weg finden, um mit der Inkonsistenz umzugehen (Ineffizienz einzuführen), oder Sie müssen einen Weg finden, um die Konsistenz sicherzustellen. Beide Ansätze sind gültig.
Joe Lapp
47

Es ist ganz einfach, die Ordnung aufrechtzuerhalten. Ich hatte das gleiche Problem mit der Aufrechterhaltung der Reihenfolge von der DB-Schicht zur UI-Schicht.

Öffnen Sie die Datei JSONObject.java. Es verwendet intern HashMap, das die Reihenfolge nicht beibehält.

Ändern Sie es in LinkedHashMap:

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

Das hat bei mir funktioniert. Lass es mich in den Kommentaren wissen. Ich schlage vor, dass die JSON-Bibliothek selbst eine andere JSONObject-Klasse haben sollte, die die Reihenfolge beibehält, wie JSONOrderdObject.java. Ich bin sehr arm bei der Auswahl der Namen.

Gary
quelle
2
svn checkout json-simple. Ändern Sie die Datei org.json.simple.JSONObject, <code> JOSNObject erweitert LinkedHashMap ... </ code> von <code> .. HashMap .. </ code>, korrigieren Sie die Importe und es funktioniert für mich. v1.1.1.
Marku
2
Dies ist eine großartige einzeilige Lösung, an die ich nie gedacht hätte. Funktioniert perfekt und ich musste keinen meiner anderen Codes ändern. +1
DaaaahWhoosh
Großartige Lösung. Sie sind ein Held Sir
Gregory Nowakowski
hat nicht funktioniert, ich habe den Import hinzugefügt, ihn geändert, wie Sie gesagt haben, habe sogar versucht, es so zu machen: this.map = new LinkedHashMap<String, Object>();funktioniert immer noch nicht. Bitte helfen Sie?
Tarek
4
Haha, wirklich? Ändern Sie die JSON-Bibliothek, um sie Ihren Anforderungen anzupassen? Ich kann mir nur vorstellen, dass dies in den Wissensdatenbanken des Unternehmens nachlässt. "Führen Sie Ihre MVN-Neuinstallation durch, laden Sie das JAR herunter, suchen Sie es, dekompilieren Sie es und ersetzen Sie HashMap durch LinkedHashMap." Dies funktioniert hervorragend für Multi-Entwickler-Teams (nicht).
Chris Neve
22

JSONObject.javanimmt jede Karte, die Sie passieren. Es kann sein LinkedHashMapoder TreeMapund es wird hashmapnur dauern , wenn die Karte null ist.

Hier ist der Konstruktor der JSONObject.javaKlasse, der die Überprüfung der Karte durchführt.

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

Bevor Sie also ein json-Objektkonstrukt erstellen LinkedHashMapund es dann wie folgt an den Konstruktor übergeben,

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

Es besteht also keine Notwendigkeit, die JSONObject.javaKlasse zu ändern . Hoffe es hilft jemandem.

Deepak Nagaraj
quelle
3
Gute Antwort, funktioniert für normales Java, funktioniert aber nicht für Android. Ich überprüfe das org.json.JSONObject in Android, es ist schade, dass Android immer noch intern erstellte Hashmap verwendet. Es werden nur Name / Wert-Paare von paramMap nach HashMap kopiert ... :(
正宗 白 布鞋
Ich habe JsonObject bestellt, aber wenn ich versuche, dieses Objekt einem JsonArray hinzuzufügen, erhalte ich ein ungeordnetes. Ich muss ein Objekt in ein Array einfügen, ich brauche Objekte in ein Array, dann setze ich einen Header in ein Array und sende es zurück. Bsp.: Ein Objekt; {CUSTOMER_SECTOR_ID = 611, CUSTOMER_NO = 0000003204, CUSTOMER_NAME = MARMARİS - KARAS GIDA KARAS TÜKETİM MADDELERİ GIDA LOJ.} Ich erhalte dies, wenn ich zwei Objekte zum Array lege: [{"CUSTOMER_NAME 0000003122 "," CUSTOMER_SECTOR_ID ":" 611 "}, {" CUSTOMER_NAME ":" M ":" 0013114714 "," CUSTOMER_SECTOR_ID ":" 611 "}] Wie Sie sehen, ist es falsch. Wie kann ich das beheben
Sahin Yanlık
2
@ Deepak Nagaraj. Ich habe Ihre Lösung ausprobiert, aber sie hat nicht funktioniert. Sie JSONObjectwird nicht als meine bestellt LinkedHashMap. Benutzt du org.jsonlib?
Ismail Sen
1
Dies ist nicht die org.jsoneine. Es definiert eine HashMapinterne, was auch immer MapSie ihm geben: @Deepak können Sie uns auf die Implementierung verweisen, die Sie verwendet haben?
Campa
8
Dies funktioniert nicht mit der org.jsonBibliothek. Wenn Sie ein neues JSONObjectObjekt erstellen und eine Karte als Argument übergeben, wird es immer in a konvertiert HashMap. Der Konstruktor erstellt zunächst eine neue Karte: this.map = new HashMap<String, Object>();und durchläuft dann Ihre Karte und kopiert jedes Element in seine HashMap.
Itachi
13

Eine ausführlichere, aber allgemein anwendbare Lösung für diese Art von Problem besteht darin, zwei Datenstrukturen zu verwenden: eine Liste mit der Reihenfolge und eine Karte mit den Beziehungen.

Zum Beispiel:

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

Sie iterieren die itemOrder-Liste und verwenden diese, um die Kartenwerte nachzuschlagen. Die Bestellung bleibt erhalten, ohne Kludges.

Ich habe diese Methode oft verwendet.

Roboterhose
quelle
Dies wird kompliziert, wenn Ihre Karte nicht nur einfache Schlüssel-Wert-Paare ist ...
zfj3ub94rf576hc4eegm
10

Eine andere hackige Lösung mit 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
quelle
1
Ich habe Ihre Antwort nicht bekommen
M. Usman Khan
1
Der Trick besteht darin, die Klasse intern so zu ändern, dass anstelle der Standard-HashMap eine LinkedHashMap verwendet wird, sodass das JSON-Objekt die Daten in der Reihenfolge hat, in der Sie sie abgelegt haben. Dies ist nicht direkt sortiert, hat aber bei mir funktioniert, da die analysierten Daten bereits sortiert sind .
Baby
sieht gut aus, aber wie man Json String AFTER map.set analysiert (json, new LinkedHashMap <> ()); weil Json String im Konstruktor übergeben wird, oder? wie neues JSONObject (jsonString).
M. Usman Khan
Auch das hat nicht funktioniert. Es gibt kein Feld "map", es gibt ein Feld "nameValuePairs", das bereits LinckedHashMap ist, und es funktioniert immer noch nicht.
M. Usman Khan
1
Welche Implementierung des JSONObject verwenden Sie? Ich verwende die org.json-Version 20140107 und musste die Reihenfolge beibehalten, und so hat es bei mir funktioniert.
Baby
6

Apache Wink hat JSONObject bestellt . Es behält die Reihenfolge beim Parsen des Strings bei.

Kirill Rakhman
quelle
4

Ich bin gerade auf dasselbe Problem gestoßen und glaube, dass die endgültige Lösung des Autors darin bestand, eine benutzerdefinierte ContainerFactory zu verwenden:

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

siehe 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
quelle
wirklich sehr gute und praktische Lösung. Wie wäre es mit einer lokalen anonymen inneren Klasse für containerFactory?
Shailesh Saxena
3

Gelöst.

Ich benutzen die JSON.simple Bibliothek von hier https://code.google.com/p/json-simple/ den JSON - String zu lesen , die Reihenfolge der Tasten zu halten und verwenden JavaCSV Bibliothek von hier http://sourceforge.net/ Projekte / javacsv / zum Konvertieren in das CSV-Format.

Hery
quelle
Ich bin überrascht, dass das funktioniert hat. Nach meiner Lektüre sowohl des Codes als auch der Kommentare der JSONObject-Klasse ( code.google.com/p/json-simple/source/browse/trunk/src/main/java/… ) wird nichts bewahrt die Reihenfolge der Schlüssel.
Stephen C
1
Ich habe hier nicht die vollständige Lösung angegeben, aber das Wesentliche ist, dass json-simple eine Factory bereitstellt, mit der Sie die Datenstruktur angeben können, die zum Speichern von json-Objekten verwendet wird. Geben Sie einfach an, dass LinkedHashMap verwendet werden soll.
Hery
@ Hery, ich stehe vor dem gleichen Problem, aber ich konnte es nicht lösen. Ich verwende org.json, um zu konvertieren List<LinkedHahMap>, JSONArrayum eine zu erstellen CSV, die CSVerstellt wird, aber nicht in der gleichen Reihenfolge wie meine List . Ich habe versucht, die beiden CSVBibliotheken zu verwenden, die Sie hier präsentieren, aber ich konnte die Methoden zum Konvertieren nicht finden. Könnten Sie bitte weitere Details angeben.
Ismail Sen
2

Ich weiß, dass dies gelöst ist und die Frage vor langer Zeit gestellt wurde, aber da ich mich mit einem ähnlichen Problem befasse, möchte ich diesbezüglich einen völlig anderen Ansatz wählen:

Für Arrays heißt es: "Ein Array ist eine geordnete Sammlung von Werten." unter http://www.json.org/ - aber Objekte ("Ein Objekt ist eine ungeordnete Menge von Name / Wert-Paaren.") werden nicht geordnet.

Ich frage mich, warum sich dieses Objekt in einem Array befindet - das impliziert eine Reihenfolge, die nicht vorhanden ist.

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

Eine Lösung wäre also, die Schlüssel in ein "echtes" Array zu legen und die Daten als Objekte zu jedem Schlüssel wie folgt hinzuzufügen:

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

Dies ist also ein Ansatz, der versucht, die ursprüngliche Modellierung und ihre Absicht zu überdenken. Aber ich habe nicht getestet (und ich frage mich), ob alle beteiligten Tools die Reihenfolge dieses ursprünglichen JSON-Arrays beibehalten würden.

cslotty
quelle
1
Dadurch kann ich den Schlüssel nicht nachschlagen.
Mickeymoon
Was willst du dann - ein Hash oder etwas bestellt!? Wenn Sie beide kombinieren möchten, erstellen Sie beide und lassen Sie eine dieser Strukturen die andere indizieren. Andernfalls scheint dies eher ein Designproblem zu sein oder Interessen zu mischen.
Cslotty
1
Es geht nicht darum, Interessen zu mischen, es ist ein ziemlich plausibler Anwendungsfall, der in Sprachen wie Java von Konstrukten wie LinkedHashMap behandelt wird, einer geordneten Karte, die die Einfügereihenfolge beibehält. Was möchte ich dann, ich möchte, dass beide in der definierten Reihenfolge die Schlüssel durchlaufen und auch die Schlüssel schnell nachschlagen können. Ich denke, die Antwort von @Robotic Pants würde ziemlich gut funktionieren, obwohl es ein bisschen hackisch ist.
Mickeymoon
Das stimmt, Mickeymoon, das wollte ich gerade sagen! Aber in JSON existiert das nicht, oder? Dann müssten Sie Sprachen / Mechanismen einbeziehen, die Ihnen so etwas bieten.
Cslotty
1

In der realen Welt verfügt eine Anwendung fast immer über eine Java-Bean oder -Domäne, die zu / von JSON serialisiert / de-serialisiert werden soll. Es wurde bereits erwähnt, dass die JSON-Objektspezifikation keine Ordnung garantiert und eine Manipulation dieses Verhaltens die Anforderung nicht rechtfertigt. Ich hatte das gleiche Szenario in meiner Anwendung, in dem ich die Ordnung nur aus Gründen der Lesbarkeit aufrechterhalten musste. Ich habe die Standardmethode von Jackson verwendet, um meine Java-Bean in JSON zu serialisieren:

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

Um den JSON mit einem geordneten Satz von Elementen zu erstellen, verwende ich einfach die JSON-Eigenschaftsanmerkung in der Java-Bean, die ich für die Konvertierung verwendet habe. Ein Beispiel unten:

@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
}

das oben verwendete getObject ():

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

Die Ausgabe zeigt gemäß der Annotation der Json-Eigenschaftsreihenfolge:

{
    name: "SomeName",
    phone: "1234567890",
    city: "SomeCity",
    id: 100
}
Vishal
quelle
0

Der sicherste Weg ist wahrscheinlich das Überschreiben der Schlüsselmethode, mit der die Ausgabe generiert wird:

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
quelle
1
Dies löst das angegebene Problem nicht. Dadurch werden die Schlüssel sortiert ... aber in der Frage wird die Einfügereihenfolge beibehalten.
Stephen C
0

patchFor (Antwort @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
quelle
0

Sie können den folgenden Code verwenden, um eine benutzerdefinierte ORDERED-Serialisierung und -Deserialisierung des JSON-Arrays durchzuführen (in diesem Beispiel wird davon ausgegangen, dass Sie Strings bestellen, diese können jedoch auf alle Typen angewendet werden):

Serialisierung

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

Deserialisierung

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
quelle
0

Ihr Beispiel:

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

füge ein Element "itemorder" hinzu

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

Dieser Code generiert die gewünschte Ausgabe ohne die Spalte Titelzeile:

JSONObject output = new JSONObject(json);
JSONArray docs = output.getJSONArray("data");
JSONArray names = output.getJSONArray("itemOrder");
String csv = CDL.toString(names,docs);
Adriano
quelle
Dies entfernte den Header der CSV, jetzt habe ich die Zeilen bestellt, aber ohne Header
Pedro Joaquín
0

Anstatt jsonObject zu verwenden, versuchen Sie es mit CsvSchema einfacher und konvertieren Sie Objekte direkt in CSV

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

und es mentains den Auftrag ID Ihre pojo hat @JsonPropertyOrder drin

rahul
quelle
0

Underscore-java behält beim Lesen von json die Reihenfolge der Elemente bei. Ich bin der Betreuer des Projekts.

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
quelle
-1

Getestet die Wink-Lösung und funktioniert gut:

@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
quelle
Maven-Abhängigkeit: <dependency> <groupId> org.apache.wink </ groupId> <artifactId> wink-json4j </ifactId> <version> 1.4 </ version> </ dependency>
jgpelaez
Gleiche Antwort wie @cypressious ... 2 Jahre zuvor gepostet. Und das Beispiel bringt keinen wirklichen Wert.
Stephen C