8

I have a class

class Foo {
  String key;
  String value;
}

and want to serialize this into "<content of key>":"<content of value>" How can I achieve this (and how to deserialize "myKey":"myVal" into a Fooobject?

I was trying to use

@JsonValue
public String toString() {
   return "\"" + key + "\":\"" + value + "\"";
}

But clearly end up with too many quotes.

@JsonValue
public String toString() {
    return key + ":" + value;
}

also does not work, as it does not create enough quotes.

Heiko Rupp
  • 30,426
  • 13
  • 82
  • 119
  • 1
    @JsonValue will simply indicate that return value should be serialized as value instead of POJO: so if you return String, it will become JSON String. There is no way to use this to add Map entries, because output context may be an array, in which case result would be invalid JSON. – StaxMan Mar 25 '11 at 18:03

1 Answers1

17

I found one way, which is using a JsonSerializer like this:

public class PropertyValueSerializer extends JsonSerializer<Foo> {

    @Override
    public void serialize(Foo property_value, JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException, JsonProcessingException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeFieldName(property_value.getKey());
        jsonGenerator.writeString(property_value.getValue());
        jsonGenerator.writeEndObject();
    }

The Foo class needs to know about this:

@JsonSerialize(using = PropertyValueSerializer.class)
public class Foo {

Deserializing is very similar:

public class PropertyValueDeserializer extends JsonDeserializer<PROPERTY_VALUE> {    

    @Override
    public Foo deserialize(JsonParser jsonParser,
                                      DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        String tmp = jsonParser.getText(); // {
        jsonParser.nextToken();
        String key = jsonParser.getText();
        jsonParser.nextToken();
        String value = jsonParser.getText();
        jsonParser.nextToken();
        tmp = jsonParser.getText(); // }

        Foo pv = new Foo(key,value);
        return pv;
    }

And this also needs to be annotated on the Foo class:

@JsonSerialize(using = PropertyValueSerializer.class)
@JsonDeserialize(using = PropertyValueDeserializer.class)
public class Foo implements Serializable{
Heiko Rupp
  • 30,426
  • 13
  • 82
  • 119
  • Yes, but why not just let it serialize as is? Just add @JsonProperty next to your fields and that should work. Or alternatively, can use @JsonAutoDetect to make Jackson "find" non-public fields too. – StaxMan Mar 25 '11 at 18:02
  • What do you mean with "as is"? class Foo {String a;String b} will be serialized into {"a":valueOfA,"b":valueOfB} ? – Heiko Rupp Mar 26 '11 at 08:57
  • Ah. So you just want to optimize it to have one entry vs two entries, got it. – StaxMan Mar 26 '11 at 17:51