如何从FasterXML\Jackson序列化/反序列化布尔值作为Int?

Ray*_*orm 19 java spring json jackson fasterxml

我正在为服务器编写一个Json客户端,它将布尔值返回为"0"和"1".当我尝试运行我的Json客户端时,我目前得到以下异常:

HttpMessageNotReadableException: Could not read JSON: Can not construct instance of java.lang.Boolean from String value '0': only "true" or "false" recognized
Run Code Online (Sandbox Code Playgroud)

那么如何设置FasterXML\Jackson来正确解析类似的东西:

{
   "SomeServerType" : {
     "ID" : "12345",
     "ThisIsABoolean" : "0",
     "ThisIsABooleanToo" : "1"
   }
}
Run Code Online (Sandbox Code Playgroud)

样本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; }
}
Run Code Online (Sandbox Code Playgroud)
@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; }
}
Run Code Online (Sandbox Code Playgroud)

Rest Client Line
注1:这是使用Spring 3.2
注2: toJSONString() - 是一个帮助方法,它使用Jackson来序列化我的参数对象
注3:读取结果对象时发生异常

DocInfoResponse result = restTemplate.getForObject(docInfoURI.toString()
                                  + "/?input={input}",
                                  DocInfoResponse.class,
                                  toJSONString(params));
Run Code Online (Sandbox Code Playgroud)

cal*_*lls 33

正如保罗佩德罗索的答案所提及和引用的那样,你需要自己定制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\"}"));
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上你不需要Deserializer:Jackson会自动将0/1反序列化为布尔POJO属性,而不需要任何注释.在我的事件中,我也不需要Serializer,因为我正在调用的服务器正在接受并转换此字段的真/假文字.无论如何,我正在给予赏金. (3认同)
  • @AndrewSpencer谢谢,我很欣赏这个奖项.:)要明确的是,杰克逊似乎会自动反序列化该属性,如果它作为**数字**而不是**字符串**. (2认同)

Sta*_*Man 5

除了自定义反序列化器之外,您还可以简单地使用一个设置器,例如:

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

因为您的方法可以声明与您内部使用的类型不同的类型。

如果您必须同时支持BooleanString,您可以指示 value 是 an Object,并检查您可能会得到什么。

Booleangetter 方法 ( ) 和 setter (StringObject)甚至应该可以有不同的类型。