Wie verwende ich einen benutzerdefinierten Serializer mit Jackson?
Ich habe zwei Java-Klassen, die ich will, zu serialisieren zu JSON mit Jackson:
public class User {
public final int id;
public final String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
public class Item {
public final int id;
public final String itemNr;
public final User createdBy;
public Item(int id, String itemNr, User createdBy) {
this.id = id;
this.itemNr = itemNr;
this.createdBy = createdBy;
}
}
Ich serialisieren möchten Sie ein Element, um dieses JSON:
{"id":7, "itemNr":"TEST", "createdBy":3}
Benutzer mit serialisiert nur die id
. Ich werde auch in der Lage sein, um serilize alle Benutzer-Objekte für JSON wie:
{"id":3, "name": "Jonas", "email": "[email protected]"}
Also denke ich, das muss ich schreiben, eine benutzerdefinierte serializer für Item
und versucht mit diesem:
public class ItemSerializer extends JsonSerializer<Item> {
@Override
public void serialize(Item value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
jgen.writeNumberField("id", value.id);
jgen.writeNumberField("itemNr", value.itemNr);
jgen.writeNumberField("createdBy", value.user.id);
jgen.writeEndObject();
}
}
Ich serialisieren der JSON mit diesem code aus Jackson How-to: Custom Serialisierungsprogramme:
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule("SimpleModule",
new Version(1,0,0,null));
simpleModule.addSerializer(new ItemSerializer());
mapper.registerModule(simpleModule);
StringWriter writer = new StringWriter();
try {
mapper.writeValue(writer, myItem);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Aber ich bekomme diese Fehlermeldung:
Exception in thread "main" java.lang.IllegalArgumentException: JsonSerializer of type com.example.ItemSerializer does not define valid handledType() (use alternative registration method?)
at org.codehaus.jackson.map.module.SimpleSerializers.addSerializer(SimpleSerializers.java:62)
at org.codehaus.jackson.map.module.SimpleModule.addSerializer(SimpleModule.java:54)
at com.example.JsonTest.main(JsonTest.java:54)
Wie kann ich das verwenden einer benutzerdefinierten Serialisierung mit Jackson?
Dies ist, wie ich es tun würde, mit Gson:
public class UserAdapter implements JsonSerializer<User> {
@Override
public JsonElement serialize(User src, java.lang.reflect.Type typeOfSrc,
JsonSerializationContext context) {
return new JsonPrimitive(src.id);
}
}
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(User.class, new UserAdapter());
Gson gson = builder.create();
String json = gson.toJson(myItem);
System.out.println("JSON: "+json);
Aber ich muss es tun mit Jackson nun, da Gson nicht haben Unterstützung für Schnittstellen.
InformationsquelleAutor der Frage Jonas | 2011-08-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wie bereits erwähnt, @JsonValue ist ein guter Weg. Aber wenn Sie nichts dagegen haben, eine benutzerdefinierte serializer, es gibt keine Notwendigkeit zu schreiben, eine für die Artikel, sondern eher eine für den Benutzer-wenn so, es würde so einfach sein wie:
Noch eine weitere Möglichkeit, ist die Umsetzung
JsonSerializable
in dem Fall ist keine Anmeldung erforderlich.Als Fehler; das ist seltsam-Sie wollen wahrscheinlich ein upgrade auf eine neuere version. Aber es ist auch sicherer zu verlängern
org.codehaus.jackson.map.ser.SerializerBase
wie es standard-Implementierungen von nicht-essentiellen Methoden (d.h. alles, aber die aktuelle Serialisierung nennen).InformationsquelleAutor der Antwort StaxMan
Können Sie setzen
@JsonSerialize(using = CustomDateSerializer.class)
über alle Datums-Feld des Objekts serialisiert werden.InformationsquelleAutor der Antwort Moesio
Ich habe versucht zu tun, zu, und es ist ein Fehler im Beispiel-code auf der Jackson-Webseite, die fehl beinhalten den Typ (.Klasse) im Aufruf addSerializer Methode, die Lesen sollte, wie diese:
In anderen Worten, dies sind die Zeilen, die Sie instanziieren, die simpleModule und fügen Sie den serializer (mit vorheriger falsche Zeile auskommentiert):
FYI: Hier ist die Referenz für die korrekte Beispiel-code: http://wiki.fasterxml.com/JacksonFeatureModules
Hoffe, das hilft!
InformationsquelleAutor der Antwort pmhargis
@JsonValue:
@JsonValue funktioniert nur auf Methoden, so dass Sie müssen hinzufügen, die getId-Methode.
Sie sollten in der Lage sein zu überspringen, Ihre benutzerdefinierte serializer insgesamt.
InformationsquelleAutor der Antwort henrik_lundgren
Diese sind Verhaltensweisen, die ich bemerkt habe, während Sie versuchen zu verstehen, Jackson Serialisierung.
1) Angenommen, es gibt ein Objekt im Klassenzimmer und eine Klasse Student. Ich habe alles öffentlich und endgültig für die Leichtigkeit.
2) davon Ausgehen, dass diese sind die serialisierungsprogramme wir verwenden für die Serialisierung der Objekte in JSON. Die writeObjectField nutzt das Objekt, die eigene Serialisierung, wenn es registriert ist, mit dem Objekt-mapper; wenn nicht, dann ist es serialisiert als ein POJO. Die writeNumberField ausschließlich nur akzeptiert primitive als Argumente.
3) Registrieren Sie sich nur ein DoubleSerializer mit DecimalFormat Ausgabe Muster
###,##0.000
im SimpleModule und die Ausgabe ist:Können Sie sehen, dass die POJO-Serialisierung unterscheidet zwischen Doppel-und Doppelbettzimmer, mit der DoubleSerialzer für Doppel-und mit einem normalen String-format für Doppelzimmer.
4) Registrieren DoubleSerializer und ClassroomSerializer, ohne die StudentSerializer. Wir erwarten, dass die Ausgabe so ist, dass wenn wir schreiben ein doppeltes, als ein Objekt, es verhält sich wie ein Doppel -, und wenn wir schreiben eine Doppelte als eine Zahl, es verhält sich wie eine doppelte. Der Student-Instanz-variable geschrieben werden soll als POJO und Folgen dem Muster oben, da es nicht registriert.
5) Registrieren alle serialisierungsprogramme. Die Ausgabe ist:
genau wie erwartet.
Ein weiterer wichtiger Hinweis: Wenn Sie mehrere serialisierungsprogramme für die gleiche Klasse mit der gleichen registriert Modul, dann wird das Modul wählen Sie die serializer für die Klasse, die zuletzt in die Liste aufgenommen. Dies sollte nicht verwendet werden - es ist verwirrend und ich bin mir nicht sicher, wie konsequent dies ist
Moral: wenn Sie anpassen möchten die Serialisierung von primitiven in Ihrem Objekt, Sie müssen schreiben Sie Ihre eigenen serializer für das Objekt. Verlassen Sie sich nicht auf die POJO-Jackson-Serialisierung.
InformationsquelleAutor der Antwort laughing_man
Jackson JSON-Ansichten vielleicht eine einfachere Möglichkeit der Erreichung Ihrer Anforderungen, vor allem, wenn Sie haben einige Flexibilität im JSON-format.
Wenn
{"id":7, "itemNr":"TEST", "createdBy":{id:3}}
ist eine akzeptable Darstellung, dann wird dieses sehr einfach zu erreichen mit sehr wenig code.Würden Sie gerade kommentieren das Feld name den Namen des Benutzers als Teil einer Ansicht, und geben Sie eine andere Ansicht in das serialisieren Anfrage (die un-annotierten Felder werden standardmäßig enthalten)
Zum Beispiel:
Definieren der Ansichten:
Kommentieren die User:
Und serialise Anforderung einer Ansicht, die nicht enthalten das Feld, das Sie ausblenden möchten (nicht-annotierten Felder sind serialisierte Standard):
InformationsquelleAutor der Antwort Paul M
In meinem Fall (Frühjahr 3.2.4 und Jackson 2.3.1), XML-Konfiguration für die benutzerdefinierte serializer:
war in unerklärliche Weise überschrieben Werkseinstellungen zurück, indem Sie etwas.
Dieser arbeitete für mich:
CustomObject.java
CustomObjectSerializer.java
Keine XML-Konfiguration (
<mvc:message-converters>(...)</mvc:message-converters>
) notwendig ist, meine Lösung.InformationsquelleAutor der Antwort user11153
Schrieb ich ein Beispiel für eine benutzerdefinierte
Timestamp.class
Serialisierung/Deserialisierung, aber Sie können es verwenden, für was immer Sie wollen.Beim erstellen der Objekt-mapper etwas wie das hier tun:
beispielsweise in
java ee
könnten Sie initialisieren es mit diesem:denen der serializer sollte so etwas wie dieses:
und deserializer so etwas wie dieses:
InformationsquelleAutor der Antwort madx
Haben Sie zum überschreiben der Methode handledType und alles funktioniert
InformationsquelleAutor der Antwort Sergey Kukurudzyak
Wenn Ihr nur die Voraussetzung in das benutzerdefinierte serializer ist zu überspringen serialisieren der
name
Bereich derUser
markieren Sie es als transient. Jackson wird nicht serialisieren oder Deserialisieren transient Felder.[ siehe auch: Warum funktioniert Java transient-Felder? ]
InformationsquelleAutor der Antwort Mike G