GSON ist eine Java -Bibliothek, mit der die gegenseitige Konvertierung zwischen JSON- und Java -Objekten implementiert wird. GSON ist ein Open -Source -Projekt, das unter https://github.com/google/gson gehostet wird.
Die Hauptklasse in GSON ist GSON. Sie können auch den GSONBuilder der Klasse verwenden, um einige Optionen festzulegen, während Sie GSON -Objekte erstellen.
GSON -Objekte speichern bei der Verarbeitung von JSON keinen Status, sodass Benutzer problemlos mehrere Serialisierung, Deserialisierung und andere Operationen auf demselben GSON -Objekt ausführen können.
Beispiel: Grundnutzung
// serializationgson gson = new gson (); gson.tojson (1); // ==> druckt 1gson.tojson ("ABCD"); // ==> Drucke "ABCD" GSON.TOJSON (New Long (10)); // ==> druckt 10Int [] values = {1}; gson.tojson (Werte); // ==> Drucke [1] // DeserializationInt One = gson.fromjson ("1", int.class); Integer eins = gson.fromjson ("1", Integer.class); lang eins = gson.fromjson ("1", Integer.class); gson.fromjson ("false", boolean.class); String str = gson.fromjson ("/" abc/"", String.ClASS); String AnotherStr = Gson.Fromjson ("[/" abc/"]", String.Class); // SerializationBagofprimitives OBJ = New Bagofives (New Bagofives (New Bagfprimitives); gson.tojson (obj); // ==> json ist {"value1": 1, "value2": "abc"}Beispiel: Konvertierung zwischen einem Objekt und einem JSON
Definieren Sie die Bagofprimitive -Klasse:
Klassenbagofprimitive {private int value1 = 1; private String value2 = "ABC"; private transient int value3 = 3; Bagofprimitive () {// no-args constructor}}Serialisiert nach JSON:
// serializationbagofprimitive obj = new Bagofprimitive (); gson gson = new gson (); String json = gson.tojson (obj); // ==> json ist {"value1": 1, "value2": "abc"}Serialisieren Sie keine Objekte, die kreisförmige Referenzen enthalten, ansonsten tritt eine unendliche Rekursion auf.
Deserialisierung:
// DeserializationBagofprimitive obj2 = gson.fromjson (JSON, BAGOFPRIMITIVES.CLASS); // ==> obj2 ist genau wie OBJ
Einige Details bei der Bearbeitung von Objekten:
Umgang mit verschachtelten Klassen (einschließlich innerer Klassen)
GSON kann leicht verschachtelte Klassen serialisieren und statische verschachtelte Klassen deserialisieren. GSON kann reine innere Klassen automatisch automatisch deserialisieren, da der parameterlose Konstruktor der inneren Klasse auf das Objekt verweisen muss, das sie enthält (d. H. Instanzen der äußeren Klasse). Um eine statische Klasse zu verdessten, können Sie die innere Klasse statisch oder einen benutzerdefinierten Instanzschöpfer angeben. Hier ist ein Beispiel:
öffentliche Klasse A {public String a; Klasse B {public String b; public b () {// No Args Konstruktor für B}}}Die obige Klasse B kann nicht von GSON serialisiert werden. Da die Klasse B eine (nicht statische) innere Klasse ist, kann GSON auch nicht in eine Instanz der Klasse B. Deserialisierung {"B": "ABC"} deserialisieren, wenn B als statische Klasse B deklariert wird, kann GSON die Zeichenfolge deserialisieren.
Eine andere Lösung besteht darin, einen Instanzschöpfer für B zu schreiben:
öffentliche Klasse InstanceCreatorForB implementiert InstoneCreator <ab> {private endgültig a a; public instangeCreatorForB (a) {this.a = a; } public ab createInstance (Typtyp) {return a.new b (); }}Diese Methode ist machbar, wird jedoch nicht empfohlen. (Der Übersetzer sagte, er habe diesen Instanzschöpfer nicht verstanden und wisse nicht, wie er es benutzt.)
Beispiel: Array
Gson gson = new gson (); int [] ints = {1, 2, 3, 4, 5}; Strings [] Strings = {"ABC", "def", "ghi"}; // serializationgson.tojson (ints); ==> Drucke [1,2,3,4,5] gson.tojson (Zeichenfolgen); ==> Drucke ["ABC", "def", "ghi"] // DeserializationInt [] ints2 = gson.fromjson ("[1,2,3,4,5]", int [].GSON unterstützt auch mehrdimensionale Arrays mit komplexen Datentypen.
Beispiel: Sammlung
Gson gson = new GSON (); Sammlung <Integer> ints = lists.immutablelist (1,2,3,4,5); // SerializationString JSON = GSON.TOJSON (INTS); // ==> JSON IS [1,2,3,4,5] // DeserializationTyPe CollectionType = new typEToken <Sammlung <Integer >> () {}. GetType (); Sammlung <Integer> ints2 = gson.fromjson (JSON, CollectionType); // ints2 is Ints2 is ints is ints is ints is ints is ints is wie ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is ints is wieEinschränkungen bei Verarbeitungssammlungen:
Serialisieren/Deserialisieren von Generika
Bei der Verwendung von Tojson (OBJ) ruft GSON OBJ.getClass () auf, um Feldinformationen für die Serialisierung zu erhalten. In ähnlicher Weise kann die Objekt -MyClass.class als Parameter an die Methode von JSON (JSON, MyClass.Class) übergeben werden, die verwendet werden kann, wenn das Objekt nicht generisch ist. Wenn das Objekt jedoch ein generisches Typ -Objekt ist, gehen die generischen Typinformationen aufgrund des Typ -Löschungsmechanismus in Java verloren. Das folgende Beispiel zeigt dies:
Klasse foo <t> {t value;} gson gson = new gson (); foo <bar> foo = new foo <bar> (); gson.tojson (foo); // darf foo.value nicht korrekt serialisieren. Fromjson (json, foo.getClass ()); // kann Foo.value als Bar nicht deserialisierenDer obige Code interpretiert den Wert als Balkentyp, da GSON foo.getClass () aufruft, um die Informationen der Klasse zu erhalten, aber diese Methode gibt eine primitive Klasse zurück, nämlich Foo.class. Dies bedeutet, dass GSON nicht wissen kann, dass dies ein Objekt vom Typ foo <bar> ist.
Um dieses Problem zu lösen, können Sie den richtigen parametrisierten Typ für Ihre Generika angeben. Sie können die TypeToken -Klasse verwenden, um es zu tun:
Type footype = new typeToken <foo <bar >> () {} .gettType (); gson.tojson (foo, footype); gson.fromjson (json, footype);Footype definiert tatsächlich eine anonyme innere Klasse, die eine GetType () -Methode enthält, mit der alle parametrisierten Typen zurückgegeben werden können.
Serialisieren/Deserialisieren einer Sammlung von Objekten jeglicher Art
Manchmal enthält der verarbeitete JSON gemischte Typen wie:
['Hallo', 5, {Name: 'Grüße', Quelle: 'Gast'}]Der entsprechende Satz sollte sein:
Collection Collection = New ArrayList (); Collection.Add ("Hallo"); Sammlung.Add (5); Sammlung.Add (neue Veranstaltung ("Grüße", "Gast");Die Ereignisklasse ist wie folgt definiert:
Klassenereignis {privater Zeichenfolge Name; private String -Quelle; private Ereignis (Zeichenfolge Name, String Quelle) {this.name = name; this.source = Quelle; }}Mit GSON müssen Sie nichts Besonderes tun, um die Sammlung zu serialisieren: Tojson (Sammlung) wird zufriedenstellende Ergebnisse ausgeben.
Die Deserialisierung durch JSON (JSON, Collection.Class) ist jedoch nicht möglich, da GSON dem Inhalt in JSON nicht mit dem Typ entsprechen kann. GSON verlangt, dass Sie eine gemeinsame Version des Sammlungstyps von JSON anbieten. Sie haben drei Möglichkeiten:
Lösung 1: Verwenden Sie die API des GSON-Parsers (Low-Level-Stream-Parser oder Dom Parser JsonParser), um Array-Elemente zu analysieren, und verwenden Sie dann GSON.Fromjson (), um jedes Array-Element zu verarbeiten. Dies ist die bevorzugte Lösung.
Schema 2: Registrieren Sie einen Typadapter für die Sammlung.Class, um Elemente im Array auf das entsprechende Objekt zuzuordnen. Der Nachteil dieser Methode besteht darin, dass sie beim Umgang mit anderen Sammelarten zu Unannehmlichkeiten führt.
Schema 3: Registrieren Sie einen Typadapter für MyCollectionMemberType und verwenden Sie die Sammlung <MyCollectionMemberMemberType> in Fromjson. Diese Methode ist nur möglich, wenn das Array wie ein hochrangiges Element aussieht oder wenn Sie den Feldtyp in die Sammlung <mycollectionMemberType> ändern können.
Eingebauter Serializer/Deserializer
GSON bietet einen Serializer/Deserializer für häufig verwendete Klassen, die möglicherweise nicht für die Standarddarstellung geeignet sind.
Hier ist eine Liste dieser Klassen:
Benutzerdefinierte Serialisierung/Deserialisierung
Manchmal ist die Standardimplementierung von GSON nicht das, was Sie wollen, was beim Umgang mit einigen Klassenbibliotheken (z. B. DateTime) häufiger ist.
Mit GSON können Sie benutzerdefinierte Serialisierer/Deserialisierer registrieren. Dazu müssen Sie die folgenden Teile implementieren:
JSON Serializer: Die Serialisierung für ein Objekt anpassen müssen
JSON Deserializer: Sie müssen den Ersteller der Deserialization -Klasse für einen Typ anpassen: Wenn ein parameterloser Konstruktor oder ein Deserializer registriert wurde, ist dies nicht erforderlich.
Gsonbuilder gson = new gsonBuilder (); gson.registerTypeadapter (mytype2.class, new MyTypeadapter (); gson.registerTypeadapter (mytype.class, new MySerializer ()); MyDeserializer ()); gson.registerTypeadapter (myType.class, New MyInstanceCreator ());
RegisterTypeTapter prüft, ob der Typadapter mehrere Schnittstellen implementiert, und registriert den Typadapter für diese Schnittstellen.
Schreiben Sie einen Serialisierer
Hier ist ein Beispiel für das Anpassen des Serializers für DateTime:
private class datetimeSerializer implementiert jsonSerializer <datenetime> {public JsonElement Serialize (DateTime SRC, TyptypOFSRC, JsonSerializationContext -Kontext) {return New JsonPrimitive (src.toString ()); }}GSON ruft tojson () auf, wenn datetime -Instanzen serialisiert werden.
Schreiben Sie einen Deserializer
Das folgende Beispiel zeigt, wie Sie einen Deserializer der DateTime -Klasse schreiben:
private class datetimedeSerializer implementiert jSondesserializer <datenetime> {public datetime Deserialize (JsonElement JSON, TypeTift, JSonDerializationContext) löst JsonParseException aus {Return New DateTime zurück (JSON.getasjsonPrimitive (). GetAsstring (); }}Wenn GSON eine JSON -String zu einem DateTime -Objekt deserialisieren muss, wird von json () aufgerufen.
Für Serializer/Deserializer sollte die Aufmerksamkeit geschenkt werden:
Schreiben Sie einen Instanzschöpfer
Bei der Deserialisierung eines Objekts muss GSON eine Instanz einer Klasse erstellen. Eine Klasse, die während der Serialisierung/Deserialisierung gut abschneidet, bedeutet, dass diese Klasse einen parameterlosen Konstruktor hat. Normalerweise ist im Zusammenhang mit Klassen ohne parameterlose Konstruktoren in einer Klassenbibliothek ein Instanzschöpfer erforderlich.
Beispiel für Schöpfer Beispiel:
Private Class MoneyInStanceCreator implementiert InstaneCreator <EMELY> {Public Money CreateInstance (Typtyp) {Neue Geld zurückgeben ("1000000", CurrencyCode.usd); }}Parametrisierter Typinstanzschöpfer
Manchmal ist der zu instanziierte Typ ein parametrisierter Typ. Insgesamt ist dies kein Problem, da die reale Instanz ein primitiver Typ ist. Hier ist ein Beispiel:
Klasse myList <T> erweitert ArrayList <T> {} Klasse myListInstanceCreator implementiert InstaneCreator <MyList <>> {@Suppresswarnings ("Deaktiviert") public myList <?> createInstance (Typtyp) {// keine parameterisierte Liste, da der tatsächliche Instanz trotzdem den rohen Typ. kehre neue mylist () zurück; }}Manchmal müssen Sie jedoch Instanzen erstellen, die auf realen parametrisierten Typen basieren. In diesem Fall können Sie den Typ -Parameter an die Erstellungsmethode übergeben. Hier ist ein Beispiel:
public class id <t> {private endgültige Klasse <T> classOfid; privater endgültiger Wert; öffentliche ID (Klasse <T> classOfid, langer Wert) {this.classofid = classOfid; this.Value = Wert; }} class idInStanceCreator implementiert InstaneCreator <id <? >> {public id <?> createInstance (Typtyp) {type [] typarameter = ((parameterizedtype) type) .getActualtualtTePeargumente (); Typ IDType = TypeParameter [0]; // ID hat nur einen parametrisierten Typ t return id.get ((Klasse) idType, 0l); }}Im obigen Beispiel kann eine Instanz der ID -Klasse nicht erstellt werden, ohne den wahren Typ an den parametrisierten Typ zu übergeben. Wir können dieses Problem lösen, indem wir den Parametertyp an die Methode weitergeben. Hier kann das Typobjekt als Darstellung der parametrisierten Java -Art von ID <Foo> angesehen werden, und die entsprechende Instanz sollte an ID <Foo> gebunden sein. Da die Klassen -ID nur einen Parameter t Parameter hat, verwenden wir GetActualtTePearGument (), um das 0. Element des Typ -Arrays in diesem Beispiel Foo.class zurückzugeben.
Kompakte Ausgabe gegen schöne Ausgabe
Die Standardausgabe von JSON in GSON befindet sich im kompakten JSON -Format. Das heißt, es gibt keine zusätzlichen Whitespace -Charaktere in JSON. Daher gibt es keinen leeren Speicherplatz zwischen dem Feldnamen und dem Feldwert zwischen Feldern und zwischen Array -Elementen in der Ausgabe von JSON. Außerdem wird das NULL -Feld nicht ausgegeben (Hinweis: Null wird in Sammel- und Array -Objekten erhalten).
Wenn Sie schöner ausgeben möchten, müssen Sie GSONBuilder verwenden, um GSON -Instanzen zu konfigurieren. JsonFormatter existiert in der öffentlichen API nicht, sodass der Client die Standardausgabeinstellungen nicht konfigurieren kann. Jetzt bieten wir nur JSONPRINTFORMATTER an, was standardmäßig 80 Zeichen pro Zeile beträgt, und die Einführung verwendet 2 Zeichen und den rechten Rand 4 Zeichen.
Das folgende Beispiel zeigt, wie eine GSON -Instanz mit einem JSONPRINTFORMATUMATUMATION verwendet wird, anstatt den Standard -JSONCOMPACTFORMATTER zu verwenden.
Gson gson = new gsonBuilder (). SetpretTypinting (). Create (); String jsonOutput = gson.tojson (einObject);
Leeres Objekt
In der Standardimplementierung von GSON werden Null -Objekte ignoriert. Dies kann das Ausgangsformat (das als Ergebnis der Serialisierung angesehen werden kann) enger machen; Der Client muss jedoch einen Standardwert dafür definieren, damit JSON normales Deserialisieren kann.
Wenn Sie eine serialisierbare GSON -Instanz -Null erstellen möchten, können Sie:
Gson gson = new GsonBuilder (). SerializeNulls (). Create ();
Beachten Sie, dass bei der Serialisierung von NULL ein JSONNull -Element zur Jsonelement -Struktur hinzugefügt wird. Daher können wir dieses Objekt (GSON) in unserem benutzerdefinierten Serializer/Deserializer verwenden.
Hier ist ein Beispiel:
public class foo {private endgültige Zeichenfolge; Private Final Int I; public foo () {this (null, 5); } public foo (String s, int i) {this.s = s; this.i = i; }} Gson gson = new gsonBuilder (). SerializeNulls (). Create (); foo foo = new foo (); String json = gson.tojson (foo); System.out.println (JSON); JSON = GSON.TOJSON (null);Ausgabe:
{"S": NULL, "I": 5} NULLVersionsunterstützung
Sie können die @Since -Annotation verwenden, um mehrere Versionen desselben Objekts aufrechtzuerhalten. Diese Annotation kann in Klassen und Feldern verwendet werden und wird auch in Zukunft bei Methoden unterstützt. Um diese Funktion zu verwenden, müssen Sie die GSON -Instanz konfigurieren, um Felder und Objekte zu ignorieren, die größer als eine bestimmte Versionsnummer sind. Wenn die Version nicht im GSON -Objekt festgelegt ist, werden alle Felder und Klassen beim Serialisieren/Deserialisieren verwendet.
Public Class VersionedClass {@Since (1.1) Private Final String Newerfield; @Since (1.0) Private Final String Newfield; privates Final String Field; public VersionedClass () {this.neWerfield = "neuer"; this.newfield = "new"; this.field = "alt"; }} VersionedClass VersionedObject = new VersionedClass (); gson gson = new gsonBuilder (). Setversion (1.0) .create (); String JsonOutput = gson.tojson (seltsamefjekt); system.out.out.println (jsonOutput); system.println (); gson.tojson (einigeObject); System.out.println (jsonOutput);Ausgabe:
{"Newfield": "New", "Field": "Old"} {"Newerfield": "neuer", "Newfield": "New", "Field": "Old"}Felder aus der Serialisierung/Deserialisierung ausschließen
GSON unterstützt die Verwendung vieler Methoden zum Entfernen von Klassen, Feldern und Feldtypen. Wenn die folgende Methode Ihren Anforderungen nicht entspricht, können Sie die maßgefertigte Serialisierungs-/Deserializer -Methode verwenden.
1. Java -Modifikatorausschluss
Wenn ein Feld als transient erklärt wird, ist das Feld standardmäßig ausgeschlossen. Wenn ein Feld statisch erklärt wird, wird dieses Feld auch standardmäßig ausgeschlossen. Wenn Sie einige Felder einfügen möchten, die als vorübergehend deklariert sind, können Sie dies tun:
importieren java.lang.reflect.modifier; gson gson = new gsonBuilder () .ExcludefieldsWithmodifiers (modifier.static) .create ();
Beachten Sie, dass Sie bei der Methode exkluzdienfields withmodifiers möglichst viele Modifikatorkonstanten verwenden können. Zum Beispiel:
Gson gson = new gsonBuilder () .ExcludefieldsWithmodifiers (modifier.static, modifier.transient, modifier.volatile) .Create ();
2. Verwenden Sie das Feld @Expose, um auszuschließen
Mit dieser Funktion können Sie bestimmte Felder in der Klasse markieren, damit sie in der Serialisierung/Deserialisierung nicht ausgeschlossen/ausgeschlossen sind. Um diese Annotation zu verwenden, sollten Sie einen GSON mit New GsonBuilder () erstellen. ExcludeFieldsWithoutexposEannotation (). Create (). Die GSON -Instanz schließt alle Felder in der Klasse aus, die nicht von @Expon markiert sind.
3.. Benutzerdefinierte Ausschlussrichtlinie
Wenn die obige Ausschlussmethode die Anforderungen nicht erfüllen kann, können Sie auch Ihre Ausschlussstrategie anpassen. Weitere Informationen finden Sie unter Ausschließungenstrategy Javadoc.
Das folgende Beispiel zeigt, wie mit @Foo markierte Felder ausgeschlossen werden und die Arten von Stringklassen oder deklarierten Feldtypen auf höchstem Niveau ausschließen:
@Retention (retentionPolicy.runtime) @target ({elementtype.field}) public @Interface foo {// Feld Tag nur Annotation} public class SampleObjectOstest {@foo Private Final int AnnotatedField; private endgültige String StringField; Private Final Long Longfield; Private Final Class <?> Clazzfield; public SampleObjectOstest () {AnnotatedField = 5; Stringfield = "SomedefaultValue"; longfield = 1234; }} public class myExclusionStrategy implementiert ExclusionStrategy {private endgültige Klasse <?> Typetoskip; private myExclusionStrategy (Klasse <?> Typetoskip) {this.typetoskip = typetoskip; } public boolean samskipClass (Klasse <?> clazz) {return (clazz == typetoskip); } public boolean samskipfield (fieldattributes f) {return f.getannotation (foo.class)! = null; }} public static void main (String [] args) {gson gson = new gsonBuilder () .setExclusionStrategies (new myExclusionStrategy (string.class)) .SerializeNulls () .Create (); SampleObjectfortest src = new SampleObjectOstest (); String json = gson.tojson (SRC); System.out.println (JSON); }Ausgabe:
{"Longfield": 1234}Unterstützung für JSON Field Benennung
Einige vordefinierte Feldnamenstrategien von GSON können Standard -Java -Feldnamen (dh Camel Nomenklatur, wie SamplefieldNameInjava) in einen JSON -Feldnamen (das ist sample_field_name_in_java oder samplefieldnameInjava) umwandeln. Weitere Informationen finden Sie unter FieldnamingPolicy.
GSON hat auch eine annotationsbasierte Richtlinie, mit der Kunden die Namen von Feldern anpassen können. Wenn ein illegaler Feldname als kommentierter Wert angegeben wird, wird GSON eine Laufzeitausnahme ausgelöst.
Das folgende Beispiel zeigt, wie diese beiden GSON -Benennungsstrategien verwendet werden:
private class einigeObject {@SerializedName ("Custom_naming") private endgültige Zeichenfolge einfeld; private Finale String ein andererfield; public SomeObject (Zeichenfolge A, Zeichenfolge b) {this.somefield = a; this.someotherfield = b; }} Einige Eintöne einObject = new EinsObject ("First", "Second"); Gson Gson = new GsonBuilder ().Ausgabe:
{"Custom_naming": "First", "Einotherfield": "Second"}Wenn Sie den Namen anpassen möchten, können Sie die Annotation @SerializedName verwenden.
Teilenstatus zwischen Serializer und Deserializer
Manchmal müssen Sie den Zustand zwischen dem Serializer und dem Deserializer teilen, und Sie können die folgenden drei Methoden verwenden, um Ihr Ziel zu erreichen:
Die ersten beiden Methoden sind nicht fadensicher, die dritte ist.
Lösung für GSON -Parsen -Nullfehler
Ein Nachteil von GSON ist, dass es keinen Null -Ersatz setzen kann.
Wir können den vom Server in Stapel zurückgegebenen Null nur manuell ersetzen. Wenn die normale Schnittstelle definiert ist, darf der Server definitiv nicht NULL zurückgeben, aber das Hintergrundergebnis wird immer null!
Wenn Sie suchen, gibt es eine gemeinsame Antwort,
Gson gson = new GsonBuilder (). SerializeNulls (). Create ();
Aber das kann das Problem nicht lösen, wie man es löst?
Die Lösung lautet wie folgt:
Gson gson = new gsonBuilder (). RegisterTypeadapterFactory (neuer nullstringToEmptyAdapterFactory ()). Create (); // Verwenden Sie dann den in der obigen Zeile geschriebenen GSON, um die Entitätsklasse zu serialisieren und zu deserialisieren. NullStringToEmptyAdapterFactory<T> implements TypeAdapterFactory { @SuppressWarnings("unchecked") public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { Class<T> rawType = (Class<T>) type.getRawType(); if (rawtype! = string.class) {return null; } return (typeadapter <t>) New StringNullAdapter (); }} // StringNullAdapter Code public class StringNullAdapter erweitert typeadapter <string> {@Override public String read (jsonReader reader) löst ioException {// todo auto-generated method stub if (reader.peek () == JSONTOKE.NULL) {{Reader. zurückkehren ""; } return reader.nextstring (); } @Override public void write (jsonwriter writer, string value) löst ioException {// Todo automatisch generierte Methode Stub ab, wenn (value == null) {writer.nullValue (); zurückkehren; } writer.Value (Wert); }}