Search code examples
javajsonspringjacksonfasterxml

How can I Serialize/De-serialize a Boolean Value from FasterXML\Jackson as an Int?


I'm writing a JSON Client for a Server that returns Boolean values as "0" and "1". When I try to run my JSON Client I currently get the following Exception:

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

So how can I setup FasterXML\Jackson to correctly parse something like:

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

Sample Pojo's:

@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
Note 1: This is using Spring 3.2
Note 2: toJSONString() - is a helper method that uses Jackson to Serialize my Parameters Object
Note 3: The Exception happens on Reading IN the result object

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

Solution

  • As Paulo Pedroso's answer mentioned and referenced, you will need to roll your own custom JsonSerializer and JsonDeserializer. Once created, you will need to add the @JsonSerialize and @JsonDeserialize annotations to your property; specifying the class to use for each.

    I have provided a small (hopefully straightforward) example below. Neither the serializer nor deserializer implementations are super robust but this should get you started.

    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\"}"));
    }