Testen von zwei JSON-Objekten auf Gleichheit ohne Berücksichtigung der untergeordneten Reihenfolge in Java

233

Ich suche nach einer JSON-Analysebibliothek, die das Vergleichen von zwei JSON-Objekten unterstützt, bei denen die untergeordnete Reihenfolge ignoriert wird, insbesondere zum Testen von JSON-Einheiten, die von einem Webdienst zurückkehren.

Unterstützt eine der wichtigsten JSON-Bibliotheken dies? Die org.json-Bibliothek führt einfach einen Referenzvergleich durch.

Jeff
quelle
1
Können nicht beide Objekte zur Zeichenfolgendarstellung serialisiert und verglichen werden? Ich denke, alle Bibliotheken unterstützen toString()das Konvertieren des Objekts in einen JSONString.
Teja Kantamneni
47
Dies setzt voraus, dass die Reihenfolge bei der Serialisierung zu und von Zeichenfolgen immer gleich ist. Ich fühle mich nicht wohl, wenn ich diese Annahme mache.
Jeff
Du hast recht, Jeff, es ist überhaupt nicht sicher. Dieser Test zeigt ein Szenario, in dem die Zuordnungen identisch sind, toString () jedoch nicht dieselbe Ausgabe zurückgibt : gist.github.com/anonymous/5974797 . Dies liegt daran, dass die zugrunde liegende HashMap wachsen kann. Wenn Sie Schlüssel entfernen, wird das interne HashMap-Array nicht verkleinert.
Guillaume Perrot

Antworten:

84

Als allgemeiner architektonischer Punkt rate ich normalerweise davon ab, Abhängigkeiten von einem bestimmten Serialisierungsformat über Ihre Speicher- / Netzwerkschicht hinaus ausbluten zu lassen. Daher würde ich zunächst empfehlen, die Gleichheit zwischen Ihren eigenen Anwendungsobjekten und nicht deren JSON-Manifestationen zu testen.

Trotzdem bin ich derzeit ein großer Fan von Jackson, was meine schnelle Lektüre der ObjectNode.equals () -Implementierung nahe legt, dass der von Ihnen gewünschte Vergleich der festgelegten Mitgliedschaft durchgeführt wird:

public boolean equals(Object o)
{
    if (o == this) return true;
    if (o == null) return false;
    if (o.getClass() != getClass()) {
        return false;
    }
    ObjectNode other = (ObjectNode) o;
    if (other.size() != size()) {
        return false;
    }
    if (_children != null) {
        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
            String key = en.getKey();
            JsonNode value = en.getValue();

            JsonNode otherValue = other.get(key);

            if (otherValue == null || !otherValue.equals(value)) {
                return false;
            }
        }
    }
    return true;
}
Piratenflagge
quelle
Diese Methode ist nicht symmetrisch, da sie nur die Teilmengenbeziehung der Kinder testet, nicht die Gleichheit. Das 'andere' Objekt hat möglicherweise mehr Kinder als in _children, und diese Methode würde immer noch true zurückgeben.
Yoni
23
@ Yoni: Nicht wahr, da es einen Größenvergleich gibt. Sie müssen genau die gleiche Anzahl von Kindern sowie die gleichen Kinder haben. @Jolly Roger: In diesem Fall serialisiere ich das Objekt nicht von JSON zurück in ein POJO, aber wenn ich JSON ein System sende, das dies tut, kann ich mich nicht darauf verlassen, dass es in genau demselben Format zurückgesendet wird, in dem ich es gesendet habe es.
Jeff
1
@ Jeff Hat das bei dir funktioniert? Im Juni schlägt assertEquals für mich fehl. Das Projekt verwendet eine alte Version (1.5), fyi.
Ronnyfm
1
Ich denke, Sie vermissen einige Tests auf hoher Ebene, wenn Sie JSON nicht behaupten. Sie könnten einen Thin-Test durchführen, der eine http-Anfrage stellt und mit einem erwarteten JSON antwortet - dies ist das Hauptfunktionsverhalten des Webdienstes.
Mogronalol
Nur ein kleiner Hinweis zur Leistung: Der Code, der 'value' mit 'otherValue' vergleicht, kann vereinfacht werden, wenn (value.equals (other.get (key)) false zurückgibt, da 'value' garantiert nicht null und ist Die equals () -Methode von JsonNode sollte ein Nullargument akzeptieren
Tillmann,
154

Probieren Sie JSONAssert von Skyscreamer aus .

Sein nicht strenger Modus hat zwei Hauptvorteile, die ihn weniger spröde machen:

  • Objekterweiterbarkeit (z. B. mit einem erwarteten Wert von {id: 1} würde dies immer noch passieren: {id: 1, moredata: 'x'} .)
  • Lose Array-Reihenfolge (zB ['Hund', 'Katze'] == ['Katze', 'Hund'])

Im strengen Modus verhält es sich eher wie die Testklasse von json-lib.

Ein Test sieht ungefähr so ​​aus:

@Test
public void testGetFriends() {
    JSONObject data = getRESTData("/friends/367.json");
    String expected = "{friends:[{id:123,name:\"Corby Page\"}"
        + ",{id:456,name:\"Solomon Duskis\"}]}";
    JSONAssert.assertEquals(expected, data, false);
}

Die Parameter im Aufruf von JSONAssert.assertEquals () sind erwartetJSONString , actualDataString und isStrict .

Die Ergebnismeldungen sind ziemlich klar, was beim Vergleich wirklich großer JSON-Objekte wichtig ist.

Carter Page
quelle
18
Ich habe diese Lösung verwendet, aber ich habe gerade festgestellt, dass Sie auch einen JSONCompareMode Ihrer Wahl bereitstellen können. Eines davon ist NON_EXTENSIBLE. Sie hätten also JSONAssert.assertEquals(expected, data, JSONCompareMode.NON_EXTENSIBLE);ungefähr Folgendes : Der Modus NON_EXTENSIBLE bedeutet, dass neue oder fehlende Felder Fehler verursachen, die Reihenfolge jedoch nicht. Die Verwendung von false würde einen milden Modus auslösen, der keine zusätzlichen oder fehlenden untergeordneten Elemente meldet.
Dan Temple
1
Der Vergleichsmodus NON_EXTENSIBLE ist genau das , wonach ich gesucht habe. Danke dafür, Dan.
ThoughtCrhyme
Bevor ich ganz aufgeregt bin: Unterstützt dies auch verschachtelte JSON-Objekte und -Arrays? :)
Christian
2
Möglicherweise möchten Benutzer dieses JSONassert-Problem berücksichtigen, bevor sie die Bibliothek verwenden. Dies weist darauf hin, dass derzeit potenzielle Lizenzprobleme mit einer Abhängigkeit von der Bibliothek vorliegen .
Chriki
3
JSONAssert-Problem Nr. 44 wurde durch den Austausch der Reinraumbibliothek in PR 67 behoben, das heute als JSONAssert 1.4.0 veröffentlicht wurde.
Carter Seite
49

Verwenden von GSON

JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");
JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);

Bearbeiten: Seit GSON v2.8.6 ist die Instanzmethode JsonParser.parseveraltet. Sie müssen die statische Methode verwenden JsonParser.parseString:

JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");
JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
axelhzf
quelle
Funktioniert in GSON 2.8.2 für mich.
Tom Saleeba
1
Es funktioniert nicht, wenn die jsonArray-Elemente nicht in Ordnung sind. Version 2.8.2
Naveen Kumar RB
1
Funktioniert nicht für mich, wenn die Reihenfolge der Objekte / Elemente unterschiedlich ist
Jknair
Es hat bei mir funktioniert, weil ich es nur für einen Unit-Test haben wollte, bei dem die beiden jsons-Eigenschaften dieselbe Reihenfolge hatten
GabrielBB
@GabrielBB Sie sollten die Frage bearbeiten und angeben, in welcher Version die API veraltet ist und in welcher Version der neue Codestil funktioniert.
klares Licht
30

Ich würde folgendes tun:

JSONObject obj1 = /*json*/;
JSONObject obj2 = /*json*/;

ObjectMapper mapper = new ObjectMapper();

JsonNode tree1 = mapper.readTree(obj1.toString());
JsonNode tree2 = mapper.readTree(obj2.toString());

return tree1.equals(tree2);
Josh
quelle
Wenn Sie Jackson bereits verwenden, ist dies meiner Meinung nach die beste Antwort.
Christoph Dietze
18
Aber das ist ein strenger Vergleich, denke ich. Es wird false für zwei gleiche json mit unterschiedlicher Reihenfolge der Elemente zurückgegeben.
Deadpool
@deadpool das Prinzip ist solide, Sie müssten nur den Vergleich ändern, um mehr involviert zu sein (z. B. nach Schlüsselfeldern suchen und nicht nach einfachen Bäumen).
Jwenting
Dies ist die beste Antwort aller Zeiten. Es beantwortet jetzt nicht nur meine Frage, sondern auch fast jeden Objektvergleich, den wir durchführen müssen. Danke, Joshu.
Luiz Feijão Veronesi
2
@deadpool, es war vielleicht ein strenger Vergleich, aber jetzt ist es nicht streng.
Andrei Damian-Fekete
18

Sie können versuchen, die JSONAssert- Klasse von json-lib zu verwenden :

JSONAssert.assertEquals(
  "{foo: 'bar', baz: 'qux'}",
  JSONObject.fromObject("{foo: 'bar', baz: 'xyzzy'}")
);

Gibt:

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>
Hertzsprung
quelle
Oder noch einfacher: JSONAssert.assertJsonEquals ("{foo: 'bar', baz: 'qux'}", {foo: 'bar', baz: 'xyzzy'} ")
Rob Juurlink
2
Während diese Lösung für die Reihenfolge der Datenelemente in JSON funktioniert, schlägt sie fehl, wenn die Reihenfolge der Elemente in Arrays nicht übereinstimmt. Wenn Ihr Code ein Set verwendet, das beispielsweise in JSON konvertiert wird. Der folgende JSON-Vergleich würde fehlschlagen: JSONAssert.assertJsonEquals( "{foo: 'bar', list: [{test: '1'}, {rest: '2'}] }", "{ foo: 'bar', list: [{rest: '2'}, {test: '1'}] }"); Mit der Nachricht:junit.framework.AssertionFailedError: : : objects differed at key [list];: arrays first differed at element [0];: objects differed at key [test];
Dan Temple
Ja, dies ist eine Einschränkung von Json :(. Json.org zeigt, dass es kein ungeordnetes Sammlungstoken gibt. {} Kann nur Schlüssel-Wert-Paare umgeben. Dies ist sehr irritierend
Merk
15

Verwenden Sie diese Bibliothek: https://github.com/lukas-krecan/JsonUnit

Pom:

<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>

IGNORING_ARRAY_ORDER - ignoriert die Reihenfolge in Arrays

assertJsonEquals("{\"test\":[1,2,3]}",
  "{\"test\":  [3,2,1]}",
  when(IGNORING_ARRAY_ORDER)
);
Chethu
quelle
Kannst du weitere Kommentare hinzufügen, wie wir es verwenden können
Ran Adler
sichere Verwendung ist sehr einfach: Fügen Sie dies Ihrem Pom hinzu. <dependency> <groupId> net.javacrumbs.json-unit </ groupId> <artifactId> json-unit </ifactId> <version> 1.5.0 </ version> <scope> test </ scope> </ dependency>
Chethu
10x Ich habe mir die Anleitung unter dem Link angesehen und sie gefunden :)
Ran Adler
12

Wenn Sie JUnit bereits verwenden, wird in der neuesten Version jetzt Hamcrest verwendet. Es ist ein generisches Matching-Framework (besonders nützlich für Unit-Tests), das erweitert werden kann, um neue Matcher zu erstellen.

Es gibt eine kleine Open-Source-Bibliothek hamcrest-jsonmit JSON-fähigen Übereinstimmungen. Es ist gut dokumentiert, getestet und unterstützt. Unten finden Sie einige nützliche Links:

Beispielcode mit Objekten aus der JSON-Bibliothek org.json.simple:

Assert.assertThat(
    jsonObject1.toJSONString(),
    SameJSONAs.sameJSONAs(jsonObject2.toJSONString()));

Optional können Sie (1) Arrays beliebiger Reihenfolge zulassen und (2) zusätzliche Felder ignorieren.

Da es eine Vielzahl von JSON-Bibliotheken für Java gibt (Jackson , GSON, json-lib, etc.), ist es sinnvoll , dass hamcrest-jsonTräger JSON Text (wie java.lang.String) sowie native Objekte von Douglas Crockford JSON - Bibliothek unterstützt org.json.

Wenn Sie JUnit nicht verwenden, können Sie Hamcrest direkt für Zusicherungen verwenden. ( Ich habe hier darüber geschrieben. )

Kevinarpe
quelle
Was ist der Vorteil der Verwendung von Hamcrast-Matchern anstelle der direkten Verwendung von JSONAssert?
Johannes
2
@ Johannes: Nur Stil.
Kevinarpe
Die hamcrest-json-Quellen haben derzeit ein letztes Festschreibungsdatum von 2012. Es wird möglicherweise nicht mehr so ​​gut unterstützt.
Thorbjørn Ravn Andersen
11

Sie können JsonUnit ausprobieren . Es kann zwei JSON-Objekte vergleichen und Unterschiede melden. Es ist auf Jackson gebaut.

Beispielsweise

assertJsonEquals("{\"test\":1}", "{\n\"test\": 2\n}");

Ergebnisse in

java.lang.AssertionError: JSON documents are different:
Different value found in node "test". Expected 1, got 2.
Lukas
quelle
6

Eine Sache, die ich getan habe und die Wunder wirkt, ist, beide Objekte in HashMap einzulesen und dann mit einem regulären assertEquals () zu vergleichen. Es wird die equals () -Methode der Hashmaps aufgerufen, die alle darin enthaltenen Objekte rekursiv vergleicht (es handelt sich entweder um andere Hashmaps oder um ein Einzelwertobjekt wie eine Zeichenfolge oder eine Ganzzahl). Dies wurde mit dem Jackson JSON-Parser von Codehaus durchgeführt.

assertEquals(mapper.readValue(expectedJson, new TypeReference<HashMap<String, Object>>(){}), mapper.readValue(actualJson, new TypeReference<HashMap<String, Object>>(){}));

Ein ähnlicher Ansatz kann verwendet werden, wenn das JSON-Objekt stattdessen ein Array ist.

Claudio Aguiar
quelle
6

Ich benutze dies und funktioniert gut für mich (mit org.json. *):

package com.project1.helpers;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class JSONUtils {

    public static boolean areEqual(Object ob1, Object ob2) throws JSONException {
        Object obj1Converted = convertJsonElement(ob1);
        Object obj2Converted = convertJsonElement(ob2);
        return obj1Converted.equals(obj2Converted);
    }

    private static Object convertJsonElement(Object elem) throws JSONException {
        if (elem instanceof JSONObject) {
            JSONObject obj = (JSONObject) elem;
            Iterator<String> keys = obj.keys();
            Map<String, Object> jsonMap = new HashMap<>();
            while (keys.hasNext()) {
                String key = keys.next();
                jsonMap.put(key, convertJsonElement(obj.get(key)));
            }
            return jsonMap;
        } else if (elem instanceof JSONArray) {
            JSONArray arr = (JSONArray) elem;
            Set<Object> jsonSet = new HashSet<>();
            for (int i = 0; i < arr.length(); i++) {
                jsonSet.add(convertJsonElement(arr.get(i)));
            }
            return jsonSet;
        } else {
            return elem;
        }
    }
}
Fänger
quelle
4

Für org.json habe ich meine eigene Lösung eingeführt, eine Methode, die mit JSONObject-Instanzen verglichen wird. Ich habe in diesem Projekt nicht mit komplexen JSON-Objekten gearbeitet, daher weiß ich nicht, ob dies in allen Szenarien funktioniert. Da ich dies in Unit-Tests verwende, habe ich mich auch nicht um Optimierungen bemüht. Hier ist es:

public static boolean jsonObjsAreEqual (JSONObject js1, JSONObject js2) throws JSONException {
    if (js1 == null || js2 == null) {
        return (js1 == js2);
    }

    List<String> l1 =  Arrays.asList(JSONObject.getNames(js1));
    Collections.sort(l1);
    List<String> l2 =  Arrays.asList(JSONObject.getNames(js2));
    Collections.sort(l2);
    if (!l1.equals(l2)) {
        return false;
    }
    for (String key : l1) {
        Object val1 = js1.get(key);
        Object val2 = js2.get(key);
        if (val1 instanceof JSONObject) {
            if (!(val2 instanceof JSONObject)) {
                return false;
            }
            if (!jsonObjsAreEqual((JSONObject)val1, (JSONObject)val2)) {
                return false;
            }
        }

        if (val1 == null) {
            if (val2 != null) {
                return false;
            }
        }  else if (!val1.equals(val2)) {
            return false;
        }
    }
    return true;
}
Victor Ionescu
quelle
1
Da Sie Optimierungen erwähnt haben :), wenn val1null ist, erhalten Sie eine NullPointerException von diesem Codeif (!val1.equals(val2)) {
JohnDoDo
Es passiert auch den Besten von uns :). +1 für die Korrektur in Ihrer Antwort.
JohnDoDo
Punkt genommen :) Hoffe, dass es nicht zu viele Stimmen bekommt, sonst wird es viel Unterstützung geben.
Victor Ionescu
1
Sie haben nicht überlegt, ob es js2ist nulloder nicht, wann js1nichtnull
Xiao
Dieser Code funktioniert nicht für verschachtelte Objekte / Sequenzen.
FabienB
3

Sie können die zjsonpatch- Bibliothek verwenden, die die Diff-Informationen gemäß RFC 6902 (JSON-Patch) darstellt. Es ist sehr einfach zu bedienen. Bitte besuchen Sie die Beschreibungsseite für die Verwendung

Gopi Vishwakarma
quelle
2

Ich würde die Bibliothek unter http://json.org/java/ nehmen und die equalsMethode von JSONObject und JSONArray ändern, um einen tiefen Gleichheitstest durchzuführen. Um sicherzustellen, dass es unabhängig von der Reihenfolge der Kinder funktioniert, müssen Sie lediglich die innere Karte durch eine ersetzen TreeMapoder etwas Ähnliches verwenden Collections.sort().

Yoni
quelle
4
es ist nicht so toll - es hätte wirklich mit Code kommen sollen, um einen json-Vergleich durchzuführen.
Chii
Aber stellen Sie sich vor, Sie schreiben diesen Code, in dem JSON alles in jeder Struktur sein kann ... schreiben Sie den Vergleich dazu! Es ist so, als würde man einen Vergleich für alle Arten von HTML-Seiten schreiben.
JPM
2

Versuche dies:

public static boolean jsonsEqual(Object obj1, Object obj2) throws JSONException

    {
        if (!obj1.getClass().equals(obj2.getClass()))
        {
            return false;
        }

        if (obj1 instanceof JSONObject)
        {
            JSONObject jsonObj1 = (JSONObject) obj1;

            JSONObject jsonObj2 = (JSONObject) obj2;

            String[] names = JSONObject.getNames(jsonObj1);
            String[] names2 = JSONObject.getNames(jsonObj1);
            if (names.length != names2.length)
            {
                return false;
            }

            for (String fieldName:names)
            {
                Object obj1FieldValue = jsonObj1.get(fieldName);

                Object obj2FieldValue = jsonObj2.get(fieldName);

                if (!jsonsEqual(obj1FieldValue, obj2FieldValue))
                {
                    return false;
                }
            }
        }
        else if (obj1 instanceof JSONArray)
        {
            JSONArray obj1Array = (JSONArray) obj1;
            JSONArray obj2Array = (JSONArray) obj2;

            if (obj1Array.length() != obj2Array.length())
            {
                return false;
            }

            for (int i = 0; i < obj1Array.length(); i++)
            {
                boolean matchFound = false;

                for (int j = 0; j < obj2Array.length(); j++)
                {
                    if (jsonsEqual(obj1Array.get(i), obj2Array.get(j)))
                    {
                        matchFound = true;
                        break;
                    }
                }

                if (!matchFound)
                {
                    return false;
                }
            }
        }
        else
        {
            if (!obj1.equals(obj2))
            {
                return false;
            }
        }

        return true;
    }
Mischa
quelle
Innerhalb von jsonArrays gibt dies true zurück, wenn einige der Elemente übereinstimmen, im Gegensatz zu allen Elementen.
Matiasg
@matiasg - stellt das if (obj1Array.length() != obj2Array.length())nicht sicher, dass alle Elemente übereinstimmen?
Kwah
3
@ Kwah: Nein. Betrachten Sie dieses Beispiel: obj1Array = [1,1,1], obj2Array = [1,2,3]. Dies würde wahr zurückgeben. Auch wenn Elemente zusammenfallen, sollten sie in derselben Reihenfolge sein. Dies würde auch für [1,2,3] und [2,3,1] zutreffen, was falsch ist
Matiasg
2

Ich weiß, dass es normalerweise nur zum Testen in Betracht gezogen wird, aber Sie könnten den Hamcrest JSON- KomparatorSameJSONAs in Hamcrest JSON verwenden.

Hamcrest JSON SameJSONAs

Justin Ohms
quelle
2

Karate ist genau das, wonach Sie suchen. Hier ist ein Beispiel:

* def myJson = { foo: 'world', hey: 'ho', zee: [5], cat: { name: 'Billie' } }
* match myJson = { cat: { name: 'Billie' }, hey: 'ho', foo: 'world', zee: [5] }

(Haftungsausschluss: dev hier)

Peter Thomas
quelle
2

Zum Vergleichen von jsons empfehle ich die Verwendung von JSONCompare: https://github.com/fslev/json-compare

// Compare by regex
String expected = "{\"a\":\".*me.*\"}";
String actual = "{\"a\":\"some text\"}";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no extra elements
String expected = "[1,\"test\",4,\"!.*\"]";
String actual = "[4,1,\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[\"text\",\"test\"]";
JSONCompare.assertEquals(expected, actual);  // True

// Check expected array has no numbers
String expected = "[\"\\\\\\d+\"]";
String actual = "[2018]";
JSONCompare.assertNotEquals(expected, actual);  // True
Slev Florin
quelle
0

Für diejenigen wie mich, die dies mit Jackson machen wollen, können Sie json-unit verwenden .

JsonAssert.assertJsonEquals(jsonNode1, jsonNode2);

Die Fehler geben nützliche Rückmeldungen zur Art der Nichtübereinstimmung:

java.lang.AssertionError: JSON documents have different values:
Different value found in node "heading.content[0].tag[0]". Expected 10209, got 10206.
krookedking
quelle
0

Nichts anderes schien ganz richtig zu funktionieren, also schrieb ich Folgendes:

private boolean jsonEquals(JsonNode actualJson, JsonNode expectJson) {
    if(actualJson.getNodeType() != expectJson.getNodeType()) return false;

    switch(expectJson.getNodeType()) {
    case NUMBER:
        return actualJson.asDouble() == expectJson.asDouble();
    case STRING:
    case BOOLEAN:
        return actualJson.asText().equals(expectJson.asText());
    case OBJECT:
        if(actualJson.size() != expectJson.size()) return false;

        Iterator<String> fieldIterator = actualJson.fieldNames();
        while(fieldIterator.hasNext()) {
            String fieldName = fieldIterator.next();
            if(!jsonEquals(actualJson.get(fieldName), expectJson.get(fieldName))) {
                return false;
            }
        }
        break;
    case ARRAY:
        if(actualJson.size() != expectJson.size()) return false;
        List<JsonNode> remaining = new ArrayList<>();
        expectJson.forEach(remaining::add);
        // O(N^2)   
        for(int i=0; i < actualJson.size(); ++i) {
            boolean oneEquals = false;
            for(int j=0; j < remaining.size(); ++j) {
                if(jsonEquals(actualJson.get(i), remaining.get(j))) {
                    oneEquals = true;
                    remaining.remove(j);
                    break;
                }
            }
            if(!oneEquals) return false;
        }
        break;
    default:
        throw new IllegalStateException();
    }
    return true;
}
Alex R.
quelle
0

Der folgende Code ist hilfreicher, um zwei JsonObject, JsonArray, JsonPrimitive und JasonElements zu vergleichen.

private boolean compareJson(JsonElement json1, JsonElement json2) {
        boolean isEqual = true;
        // Check whether both jsonElement are not null
        if (json1 != null && json2 != null) {

            // Check whether both jsonElement are objects
            if (json1.isJsonObject() && json2.isJsonObject()) {
                Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1).entrySet();
                Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2).entrySet();
                JsonObject json2obj = (JsonObject) json2;
                if (ens1 != null && ens2 != null) {
                    // (ens2.size() == ens1.size())
                    // Iterate JSON Elements with Key values
                    for (Entry<String, JsonElement> en : ens1) {
                        isEqual = isEqual && compareJson(en.getValue(), json2obj.get(en.getKey()));
                    }
                } else {
                    return false;
                }
            }

            // Check whether both jsonElement are arrays
            else if (json1.isJsonArray() && json2.isJsonArray()) {
                JsonArray jarr1 = json1.getAsJsonArray();
                JsonArray jarr2 = json2.getAsJsonArray();
                if (jarr1.size() != jarr2.size()) {
                    return false;
                } else {
                    int i = 0;
                    // Iterate JSON Array to JSON Elements
                    for (JsonElement je : jarr1) {
                        isEqual = isEqual && compareJson(je, jarr2.get(i));
                        i++;
                    }
                }
            }

            // Check whether both jsonElement are null
            else if (json1.isJsonNull() && json2.isJsonNull()) {
                return true;
            }

            // Check whether both jsonElement are primitives
            else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
                if (json1.equals(json2)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else if (json1 == null && json2 == null) {
            return true;
        } else {
            return false;
        }
        return isEqual;
    }
Radadiya Nikunj
quelle
0

Als ich mir die Antworten ansah, versuchte ich es mit JSONAssert, aber es schlug fehl. Also habe ich Jackson mit zjsonpatch benutzt. Ich habe Details in der SO-Antwort hier gepostet .

Likejudo
quelle
-5

Diese Lösung ist für mich sehr gut:

try {           
                // Getting The Array "Courses" from json1 & json2   
                Courses1 =json1.getJSONArray(TAG_COURSES1);
                Courses2 = json2.getJSONArray(TAG_COURSES);

                //LOOP FOR JSON1
                for(int i = 0; i < Courses1.length(); i++){
                    //LOOP FOR JSON2
                    for(int ii = 0; ii < Courses2.length(); ii++){
                        JSONObject courses1 = Courses1.getJSONObject(i);
                        JSONObject courses2 = Courses2.getJSONObject(ii);

                        // Storing each json1 item in variable
                        int courseID1 = courses1.getInt(TAG_COURSEID1);
                        Log.e("COURSEID2:", Integer.toString(courseID1));
                        String Rating1 = courses1.getString(TAG_RATING1);
                        int Status1 = courses1.getInt(TAG_STATUS1);
                        Log.e("Status1:", Integer.toString(Status1));      //Put the actual value for Status1 in log.             

                        // Storing each json2 item in variable
                        int courseID2 = courses2.getInt(TAG_COURSEID);
                        Log.e("COURSEID2:", Integer.toString(courseID));   //Put the actual value for CourseID in log
                        String Title2 = courses2.getString(TAG_TITLE);                      
                        String instructor2 = courses2.getString(TAG_INSTRUCTOR);
                        String length2 = courses2.getString(TAG_LENGTH);
                        String rating2 = courses2.getString(TAG_RATING);
                        String subject2 = courses2.getString(TAG_SUBJECT);
                        String description2 = courses2.getString(TAG_DESCRIPTION);

                        //Status1 = 5 from json1; Incomplete, Status1 =-1 Complete 
                        if(Status1 == 5 && courseID2 == courseID1){                                  

                        // creating new HashMap
                        HashMap<String, String> map = new HashMap<String, String>();         
                        //Storing the elements if condition is true.
                        map.put(TAG_COURSEID, Integer.toString(courseID2)); //pend for compare
                        map.put(TAG_TITLE, Title2);
                        map.put(TAG_INSTRUCTOR, instructor2);
                        map.put(TAG_LENGTH, length2);
                        map.put(TAG_RATING, rating2);
                        map.put(TAG_SUBJECT, subject2); //show it
                        map.put(TAG_DESCRIPTION, description2);

                        //adding HashList to ArrayList
                        contactList.add(map);
                        }//if
                    }//for2 (json2)
                } //for1 (json1)                
            }//Try

Hoffe das hilft anderen.

JLouis
quelle
Natürlich, geben Sie in diesem Fall einfach Ihre Werte und Bedingungen sowie die Art der Sichtweise an. Hashmap über eine Listenansicht.
JLouis
1
Dies ist ein schönes Beispiel dafür, wie man es nicht macht :)
Petr Újezdský