web-dev-qa-db-ja.com

FasterXML \ Jacksonのブール値をIntとしてシリアル化/逆シリアル化するにはどうすればよいですか?

Boolean値を「0」および「1」として返すサーバー用のJSONクライアントを作成しています。 JSONクライアントを実行しようとすると、現在次の例外が発生します。

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

したがって、次のようなものを正しく解析するためにFasterXML\Jacksonを設定するにはどうすればよいですか?

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

サンプルの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; }
}

残りのクライアント行
注1:これはSpring 3.2を使用しています
注2:toJSONString()-Jacksonを使用してパラメーターオブジェクトをシリアル化するヘルパーメソッドです。
注3:例外は、結果オブジェクトのINの読み取りで発生します

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

Paulo Pedrosoの回答が言及および参照したように、独自のカスタムJsonSerializerおよびJsonDeserializerをロールする必要があります。作成したら、@JsonSerializeおよび@JsonDeserialize注釈をプロパティに追加する必要があります。それぞれに使用するクラスを指定します。

以下に小さな(できれば簡単な)例を示しました。シリアライザーとデシリアライザーの実装はどちらも非常に堅牢ではありませんが、これで開始できます。

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

カスタムデシリアライザーの代わりに、次のようなセッターを単純に使用することもできます。

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

メソッドは内部で使用するものとは異なる型を要求できるためです。

BooleanStringの両方をサポートする必要がある場合は、値がObjectであることを示し、何が得られるかを確認できます。

Getterメソッド(Boolean)とsetter(StringまたはObject)に異なる型を使用することも可能です。

4
StaxMan