简体   繁体   中英

Serialize class with generic to JSON using Jackson

I have a structure of objects representing a Questionnaire and I need to serialize to JSON. One class of the structure is a OpenQuestion and this class use generics with two parameters. The problem starts when one of types used was Date, the date is serialized wrong, like a long.

Class code:

public class OpenQuestion <valueType,validationType> extends AbstractQuestion implements    Serializable {
    private valueType value;
    private validationType minValue;
    private validationType maxValue;
    ...
}

I saw how to serialize a date in a hash map if the hash map always uses a Date, but in this case I use the class with String, Integer or Date.

Any idea to solve it? Thanks

You can add a JsonTypeInfo annotation for this. There's two ways of using this:

  • Get it to automatically add a type annotation to your object, so it knows what to deserialize it as.
  • Add a custom type resolver, to handle this for you.

The first will make your JSON ugly, but requires very little extra code and doesn't force you to make custom serializers. The latter is more difficult, but will result in cleaner JSON. Overall the problem is partly that one of your types isn't modelled in JSON (Date) so you'll probably need it to be serialised as an integer or String type in your JSON file.

The former option looks a bit like this:

@JsonTypeInfo( use = Id.CLASS, include = As.WRAPPER_PROPERTY )
private valiationType minValue;

This should encode say, a String value, as something like:

{ __type = "java.lang.String", value = "Hello, World" }

No promises on that being accurate as this is mostly from memory!

It depends. If you do know expected type, you just pass generic type reference:

OpenQuestion<Value,Validation> v = objectMapper.readValue(json,
  new TypeReference<OpenQuestion<Value,Validation>>() { });

as that clues Jackson in as to expected type.

If you do not know it, then the other answer shows how to use @JsonTypeInfo .

As pointed out by @MiserableVariable, Jackson serializes (most) date fields as (numeric long) timestamps by default. You can override this behavior in a number of ways.

If using your own instance of ObjectMapper, override a property to write dates as ISO-8601:

objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);

If using your own instance of ObjectMapper, to have dates written in your own custom format:

objectMapper.setDateFormat(myDateFormat); // 1.8 and above
objectMapper.getSerializationConfig().setDateFormat(myDateFormat); // for earlier versions (deprecated for 1.8+)

To leave the default serialization behavior for most fields, but override it for certain fields on certain objects, use a custom serializer:

public class MyBean implements Serializable {
    private Date postDate;

    // ... constructors, etc

    @JsonSerialize(using = MyCustomDateSerializer.class)
    public Date getPostDate() {
        return postDate;
    }
}

public class MyCustomDateSerializer extends JsonSerializer<Date> {

    @Override
    public void serialize(final Date date, final JsonGeneraror generator,
          final SerializerProvider provider) throws IOException,
          JSONProcessingException {

        generator.writeString(yourRepresentationHere);
    }
}

All of this information is available in the Jackson Documentation , with the bulk of it in the section dealing with date handling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM