Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

json deserialization issue with h2 while testing

Tags:

java

json

h2

I have the following hibernate entity

@Data
@Entity
@TypeDef(
        typeClass = JsonStringType.class,
        defaultForType = MetaData.class
)
public class DbEntity(){
    @Column(name = "id", unique = true, nullable = false)
    private String id;

    @Column(name = "user_id", nullable = false, updatable = false)
    private String userId;

    @Column(name = "meta_data", columnDefinition = "json")
    private MetaData metaData;
}

The MetaData class is as follows:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MetaData {
    private Long amount;
    private Date date;
}

The metadata field is stored as json in db. This works with mysql. But I'm writing tests using h2 and am not able to read values in field metaData.

Exception I'm getting is:

Exception: The given string value: "{\"amount\":100,\"date\":1593690610000}" cannot be transformed to Json object
..
..
Caused by: java.lang.IllegalArgumentException: The given string value: "{\"amount\":100,\"date\":1593690610000}" cannot be transformed to Json object
..
..
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `foo.bar.MetaData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{\"amount\":100,\"date\":1593690610000}')
 at [Source: (String)""{\"amount\":100,\"date\":1593690610000}""; line: 1, column: 1]

I'm using 1.4.200 version of h2.

Most of the solutions mentioned for the problem are around h2 supporting json or jsonb. But my version of h2 supports json.

Also, if I remove columnDefinition = "json" from @Column of metaData, tests work as expected. But, in that case, mysql implementation doesn't work.

This h2 official page suggests to add FORMAT JSON in insert sql statement. But I'm not sure how to add it as I'm using hibernate.

like image 933
santosh-patil Avatar asked Jul 20 '26 13:07

santosh-patil


1 Answers

If you don't have a really good reason to use json columns, just change de columnDefinition attribute in @Column

@Column(name = "meta_data", columnDefinition = "text")
@Convert(converter = JsonConverter.class)
private MetaData metaData;

And define a custom converter:

@Converter
public static class JsonConverter implements AttributeConverter<MetaData, String> {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    @SneakyThrows
    public String convertToDatabaseColumn(MetaData metaData) {
        return mapper.writeValueAsString(metaData);
    }

    @Override
    @SneakyThrows
    public MetaData convertToEntityAttribute(String s) {
        return mapper.readValue(s, MetaData.class);
    }

}
like image 100
madrileño Avatar answered Jul 23 '26 02:07

madrileño



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!