web-dev-qa-db-fra.com

Comment puis-je sérialiser / désérialiser une valeur booléenne de FasterXML \ Jackson en tant qu'int?

J'écris un client JSON pour un serveur qui renvoie des valeurs booléennes comme "0" et "1". Lorsque j'essaie d'exécuter mon client JSON, j'obtiens actuellement l'exception suivante:

HttpMessageNotReadableException: Could not read JSON: Can not construct instance of Java.lang.Boolean from String value '0': only "true" or "false" recognized

Alors, comment puis-je configurer FasterXML\Jackson pour analyser correctement quelque chose comme:

{
   "SomeServerType" : {
     "ID" : "12345",
     "ThisIsABoolean" : "0",
     "ThisIsABooleanToo" : "1"
   }
}

Exemple de Pojo:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"someServerType"})
public class myPojo
{
   @JsonProperty("someServerType")
   SomeServerType someServerType;

   @JsonProperty("someServerType")
   public SomeServerType getSomeServerType() { return someServerType; }

   @JsonProperty("someServertype")
   public void setSomeServerType(SomeServerType type)
   { someServerType = type; }
}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"someServerType"})
public class SomeServerType 
{
   @JsonProperty("ID")
   Integer ID;

   @JsonProperty("ThisIsABoolean")
   Boolean bool;

   @JsonProperty("ThisIsABooleanToo")
   Boolean boolToo;

   @JsonProperty("ID")
   public Integer getID() { return ID; }

   @JsonProperty("ID")
   public void setID(Integer id)
   { ID = id; }

   @JsonProperty("ThisIsABoolean")
   public Boolean getThisIsABoolean() { return bool; }

   @JsonProperty("ThisIsABoolean")
   public void setThisIsABoolean(Boolean b) { bool = b; }

   @JsonProperty("ThisIsABooleanToo")
   public Boolean getThisIsABooleanToo() { return boolToo; }

   @JsonProperty("ThisIsABooleanToo")
   public void setThisIsABooleanToo(Boolean b) { boolToo = b; }
}

Rest Client Line
Remarque 1: Ceci utilise Spring 3.2
Remarque 2: toJSONString () - est une méthode d'aide qui utilise Jackson pour sérialiser mon objet de paramètres
Remarque 3: L'exception se produit le Lecture IN l'objet résultat

DocInfoResponse result = restTemplate.getForObject(docInfoURI.toString()
                                  + "/?input={input}",
                                  DocInfoResponse.class,
                                  toJSONString(params));
19
Raystorm

Comme la réponse de Paulo Pedroso l'a mentionné et référencé, vous devrez rouler vos propres JsonSerializer et JsonDeserializer personnalisés. Une fois créé, vous devrez ajouter le @JsonSerialize et @JsonDeserialize annotations à votre propriété; spécifiant la classe à utiliser pour chacun.

J'ai fourni un petit exemple (espérons-le simple) ci-dessous. Ni les implémentations du sérialiseur ni du désérialiseur ne sont super robustes, mais cela devrait vous aider à démarrer.

public static class SimplePojo {

    @JsonProperty
    @JsonSerialize(using=NumericBooleanSerializer.class)
    @JsonDeserialize(using=NumericBooleanDeserializer.class)
    Boolean bool;
}

public static class NumericBooleanSerializer extends JsonSerializer<Boolean> {

    @Override
    public void serialize(Boolean bool, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeString(bool ? "1" : "0");
    }   
}

public static class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {

    @Override
    public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
        return !"0".equals(parser.getText());
    }       
}

@Test
public void readAndWrite() throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();

    // read it
    SimplePojo sp = mapper.readValue("{\"bool\":\"0\"}", SimplePojo.class);
    assertThat(sp.bool, is(false));

    // write it
    StringWriter writer = new StringWriter();
    mapper.writeValue(writer, sp);
    assertThat(writer.toString(), is("{\"bool\":\"0\"}"));
}
33
callmepills

Au lieu d'un désérialiseur personnalisé, vous pouvez également simplement avoir un setter comme:

public void setThisIsABoolean(String str) {
  if ("0".equals(str)) {
    bool = false;
  } else {
    bool = true;
  }
}

car votre méthode peut revendiquer un type différent de celui que vous utilisez en interne.

Et si vous devez prendre en charge Boolean et String, vous pouvez indiquer que la valeur est un Object et vérifier ce que vous pourriez obtenir.

Il devrait même être possible d'avoir un type différent pour la méthode getter (Boolean) et setter (String ou Object).

4
StaxMan