String als Liste der Strings deserialisieren

Sep 23 2020

Ich habe ein POJO, das die folgenden Attribute enthält

public class Example {
  @JsonProperty("inputFoo")
  private String foo
  @JsonProperty("inputBar")
  private String bar
  @JsonProperty("inputBaz")
  @JsonDeserialize(using = MyDeserializer.class)
  private Set<String> baz
}

Der JSON, mit dem ich arbeite, um diese Daten darzustellen, repräsentiert derzeit das baz-Attribut als einzelne Zeichenfolge:

{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}

Ich verwende den Jackson ObjectMapper, um zu versuchen, den JSON in mein POJO zu konvertieren. Ich weiß, dass der Eingabe-Baz-String aus dem JSON dem Set, als das ich ihn darstellen möchte, nicht sauber zugeordnet werden kann. Daher habe ich einen benutzerdefinierten Deserializer definiert:

public class MyDeserializer extends StdDeserializer<Set<String>> {
   public MyDeserializer(){}

   public MyDeserializer(Class<?> vc) {
      super(vc);
   }

   public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
      String input = p.readValueAs(String.class);
      Set<String> output = new HashSet<>();
      if(input != null) {
         output.add(input);
      }
      return output;
   }
}

Ich erhalte eine IllegalArgumentException, die auf das Attribut "inputBaz" verweist, zu dem ich Details bereitstellen kann. Hat jemand ein offensichtliches Problem mit meiner Deserializer-Implementierung gesehen? Vielen Dank

Antworten

2 MichałZiober Sep 22 2020 at 23:33

Sie müssen keinen benutzerdefinierten Deserialisierer implementieren. Verwenden Sie die Funktion ACCEPT_SINGLE_VALUE_AS_ARRAY . Es funktioniert auch für Sets:

Funktion, die bestimmt, ob es akzeptabel ist, Nicht-Array-Werte (in JSON) für die Arbeit mit Java-Auflistungstypen (Arrays, java.util.Collection) zu erzwingen . Wenn diese Option aktiviert ist, versuchen Sammlungsdeserialisierer, Nicht-Array-Werte so zu behandeln, als hätten sie das JSON-Array "implizit" umgeben. Diese Funktion soll aus Kompatibilitäts- / Interoperabilitätsgründen verwendet werden, um mit Paketen (z. B. XML-zu-JSON-Konvertern) zu arbeiten, die das JSON-Array auslassen, wenn nur ein einziges Element im Array vorhanden ist. Die Funktion ist standardmäßig deaktiviert.

Siehe auch:

  • com.fasterxml.jackson.databind.exc.MismatchedInputException: Instanz von java.util.ArrayListout of START_OBJECT-Token kann nicht deserialisiert werden
Andreas Sep 22 2020 at 23:44

Ersetzen Sie die 2 Konstruktoren durch diesen Konstruktor ohne Argumente:

public MyDeserializer() {
    super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
pirho Sep 23 2020 at 02:00

ACCEPT_SINGLE_VALUE_AS_ARRAY wie vorgeschlagen ist eine gute Option.

Vielleicht ist Ihr eigentliches Problem komplizierter, aber wenn nicht, können Sie es auch @JsonCreatoranstelle eines benutzerdefinierten Deserialisierers versuchen . Mögen:

public class Example {

    @JsonCreator
    public Example(@JsonProperty("inputFoo") String foo,
            @JsonProperty("inputBar") String bar,
            @JsonProperty("inputBaz") String strBaz) {
        this.foo = foo;
        this.bar = bar;
        this.baz = new HashSet<>();
        baz.add(strBaz);
    }

    private String foo;
    private String bar;
    private Set<String> baz;
}

Nur um zu zeigen, dass Sie im Allgemeinen die Implementierung eines benutzerdefinierten Deserializers mit vermeiden können, @JsonCreatoraber dennoch einige einfache Konvertierungen vornehmen.