How to automatically serialize and deserialize JSON string using JPA and Hibernate?

Can achieve this using JPA Converter.

Entity;

@Id
@GeneratedValue
Long id;

@Column(name = "mapvalue")
@Convert(converter = MapToStringConverter.class)
Map<String, String> mapValue;

Converter:

@Converter
public class MapToStringConverter implements AttributeConverter<Map<String, String>, String> {

    ObjectMapper mapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(Map<String, String> data) {
        String value = "";
        try {
            value = mapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return value;
    }

    @Override
    public Map<String, String> convertToEntityAttribute(String data) {
        Map<String, String> mapValue = new HashMap<String, String>();
        TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {
        };
        try {
            mapValue = mapper.readValue(data, typeRef);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return mapValue;
    }

}

Saving data :

Map<String, String> mapValue = new HashMap<String, String>();
mapValue.put("1", "one");
mapValue.put("2", "two");
DataEntity entity = new DataEntity();
entity.setMapValue(mapValue);
repo.save(entity);

The value will store in DB as

{"1":"three","2":"two"}

Honestly I think your best solution is to create a separate table (preference) for your properties.

+------------+
| preference |
+------------+---------+------+-----+
| Field      | Type    | Null | Key |
+------------+---------+------+-----+
| user_id    | bigint  | NO   | PRI |
| key        | varchar | NO   | PRI |
| value      | varchar | NO   |     |
+------------+---------+------+-----+

You can map this in your entity like this:

@Entity
public class User
{
    @Id
    private Long id;

    @ElementCollection
    @MapKeyColumn(name = "key")
    @Column(name = "value")
    @CollectionTable(name = "preference",
        joinColumns = @JoinColumn(name = "user_id"))
    private Map<String, String> preferences;
}

This way your database is more normalized and you don't have to fool around with 'creative solutions' like storing preferences as JSON.


It's very easy to persist JSON objects using Hibernate.

You don’t have to create all these types manually, you can simply get them via Maven Central using the following dependency:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version> 
</dependency> 

For more info, check out the Hibernate Types open-source project.

Now, you need to add this @TypeDef annotation on the class level or in a package-info.java package-level descriptor to use the JsonBinaryType Hibernate Type:

@TypeDef(
    name = "jsonb",
    typeClass = JsonBinaryType.class
)

And the entity mapping will look like this:

@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private String preferences;

That's it!