Wie kann ich eine JSON-Zeichenfolge deserialisieren, die Aufzählungswerte enthält, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird? (mit Jackson Databind)
Die JSON-Zeichenfolge:
[{"url": "foo", "type": "json"}]
und mein Java POJO:
public static class Endpoint {
public enum DataType {
JSON, HTML
}
public String url;
public DataType type;
public Endpoint() {
}
}
In diesem Fall würde das Deserialisieren des JSON mit "type":"json"
fehlschlagen, wo "type":"JSON"
dies funktionieren würde. Aber ich möchte "json"
auch aus Gründen der Namenskonvention arbeiten.
Die Serialisierung des POJO führt auch zu Großbuchstaben "type":"JSON"
Ich dachte an @JsonCreator
und @JsonGetter:
@JsonCreator
private Endpoint(@JsonProperty("name") String url, @JsonProperty("type") String type) {
this.url = url;
this.type = DataType.valueOf(type.toUpperCase());
}
//....
@JsonGetter
private String getType() {
return type.name().toLowerCase();
}
Und es hat funktioniert. Aber ich habe mich gefragt, ob es eine bessere Lösung gibt, weil das für mich wie ein Hack aussieht.
Ich kann auch einen benutzerdefinierten Deserializer schreiben, aber ich habe viele verschiedene POJOs, die Aufzählungen verwenden, und es wäre schwierig, sie zu warten.
Kann jemand einen besseren Weg vorschlagen, um Enums mit der richtigen Namenskonvention zu serialisieren und zu deserialisieren?
Ich möchte nicht, dass meine Aufzählungen in Java in Kleinbuchstaben geschrieben werden!
Hier ist ein Testcode, den ich verwendet habe:
String data = "[{\"url\":\"foo\", \"type\":\"json\"}]";
Endpoint[] arr = new ObjectMapper().readValue(data, Endpoint[].class);
System.out.println("POJO[]->" + Arrays.toString(arr));
System.out.println("JSON ->" + new ObjectMapper().writeValueAsString(arr));
Antworten:
In Version 2.4.0 können Sie einen benutzerdefinierten Serializer für alle Enum-Typen registrieren ( Link zum Github-Problem). Sie können auch den Standard-Enum-Deserializer selbst ersetzen, der den Enum-Typ kennt. Hier ist ein Beispiel:
Ausgabe:
quelle
Jackson 2.9
Dies ist jetzt mit
jackson-databind
2.9.0 und höher sehr einfachVollständiges Beispiel mit Tests
quelle
jackson-databind
2.9.2 funktioniert speziell wie erwartet.spring.jackson.mapper.accept-case-insensitive-enums=true
Ich bin in meinem Projekt auf dasselbe Problem gestoßen. Wir haben beschlossen, unsere Aufzählungen mit einem String-Schlüssel und einer Verwendung
@JsonValue
sowie einem statischen Konstruktor für die Serialisierung bzw. Deserialisierung zu erstellen .quelle
DataType.valueOf(key.toUpperCase())
- ansonsten haben Sie nichts wirklich geändert. Defensivesreturn (null == key ? null : DataType.valueOf(key.toUpperCase()))
key
Feld unnötig. IngetKey
, Sie könnten geradereturn name().toLowerCase()
Seit Jackson 2.6 können Sie dies einfach tun:
Ein vollständiges Beispiel finden Sie in diesem Kern .
quelle
Ich habe mich für die Lösung von Sam B. entschieden, aber für eine einfachere Variante.
quelle
DataType.valueOf(key.toUpperCase())
ist eine direkte Instanziierung, bei der Sie eine Schleife haben. Dies könnte ein Problem für eine sehr große Anzahl sein. Sie können natürlichvalueOf
eine IllegalArgumentException auslösen, die Ihr Code vermeidet. Dies ist also ein guter Vorteil, wenn Sie die Nullprüfung der Ausnahmeprüfung vorziehen.Wenn Sie Spring Boot
2.1.x
mit Jackson verwenden2.9
, können Sie einfach diese Anwendungseigenschaft verwenden:spring.jackson.mapper.accept-case-insensitive-enums=true
quelle
Für diejenigen, die versuchen, Enum zu deserialisieren, wobei Groß- und Kleinschreibung in GET-Parametern ignoriert wird , hilft das Aktivieren von ACCEPT_CASE_INSENSITIVE_ENUMS nichts. Es wird nicht helfen, da diese Option nur für die Deserialisierung des Körpers funktioniert . Versuchen Sie stattdessen Folgendes:
und dann
Die Antwort- und Codebeispiele finden Sie hier
quelle
Mit Entschuldigungen an @Konstantin Zyubin war seine Antwort nah an dem, was ich brauchte - aber ich habe es nicht verstanden, also denke ich, dass es so gehen sollte:
Wenn Sie einen Aufzählungstyp als Groß- und Kleinschreibung deserialisieren mögen - das heißt , Sie wollen nicht, oder nicht, ändern Sie das Verhalten der gesamten Anwendung, können Sie einen benutzerdefinierten Deserializer erstellen nur für eine Art - von Unter classing
StdConverter
und Kraft Jackson verwendet es nur auf den relevanten Feldern mit demJsonDeserialize
Anmerkung.Beispiel:
quelle
Das Problem wird an com.fasterxml.jackson.databind.util.EnumResolver weitergeleitet . Es verwendet HashMap, um Aufzählungswerte zu speichern, und HashMap unterstützt keine Schlüssel, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird.
In den obigen Antworten sollten alle Zeichen in Groß- oder Kleinbuchstaben geschrieben sein. aber ich habe alle (un) sensiblen Probleme für Enums damit behoben:
https://gist.github.com/bhdrk/02307ba8066d26fa1537
CustomDeserializers.java
Verwendung:
quelle
Ich habe eine Modifikation der Iago Fernández- und Paul-Lösung verwendet.
Ich hatte eine Aufzählung in meinem Anfrageobjekt, bei der die Groß- und Kleinschreibung nicht berücksichtigt werden musste
quelle
Fügen Sie einfach die folgende Eigenschaft zur
application.properties
Datei Ihres Spring-Boot-Projekts hinzu, um die Deserialisierung von Aufzählungen in Jackson ohne Berücksichtigung der Groß- und Kleinschreibung zu ermöglichen .Wenn Sie die yaml-Version der Eigenschaftendatei haben, fügen Sie Ihrer
application.yml
Datei die folgende Eigenschaft hinzu .quelle
So gehe ich manchmal mit Aufzählungen um, wenn ich ohne Berücksichtigung der Groß- und Kleinschreibung deserialisieren möchte (basierend auf dem in der Frage angegebenen Code):
Wenn die Aufzählung nicht trivial ist und sich daher in einer eigenen Klasse befindet, füge ich normalerweise eine statische Analysemethode hinzu, um Zeichenfolgen in Kleinbuchstaben zu verarbeiten.
quelle
Enumeration mit Jackson zu deserialisieren ist einfach. Wenn Sie eine auf String basierende Enumeration deserialisieren möchten, benötigen Sie einen Konstruktor, einen Getter und einen Setter für Ihre Enumeration. Auch Klassen, die diese Enumeration verwenden, müssen einen Setter haben, der DataType als Parameter empfängt, nicht String:
Wenn Sie Ihren JSON haben, können Sie mit ObjectMapper of Jackson in die Endpoint-Klasse deserialisieren:
quelle