Clean • Professional
Modern applications often deal with flexible, dynamic, or semi-structured data such as user preferences, metadata, configurations, and external API responses.
Storing such data in fixed relational columns can be restrictive and lead to unnecessary schema complexity.
This is where JSON data mapping becomes useful.
Spring Boot + JPA, together with database support (especially PostgreSQL), allows you to store and read JSON objects directly from database columns while still working with Java objects.

| Feature | JSON | JSONB |
|---|---|---|
| Storage | Stored as plain text | Stored in optimized binary format |
| Query Performance | Slower, needs parsing on each query | Faster, parsed once and reused |
| Index Support | Limited indexing support | Excellent indexing (GIN / GiST) |
| Ordering Preserved | Yes, key order is preserved | No, key order is not preserved |
| Duplicate Keys | Allowed | Removed automatically |
| Recommended Usage | Rarely used | Preferred for most use cases |
JSON mapping helps when:
Avoid JSON for:
Hibernate Types is the recommended and industry-standard approach for mapping JSON / JSONB columns in Spring Boot + JPA applications.
Step 1: Add Dependency
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-60</artifactId>
<version>2.21.1</version>
</dependency>
Why this library?
Step 2: Entity Mapping with JSONB
@Entity
@TypeDef(name = "json", typeClass = JsonType.class)
@Table(name = "users")
publicclassUser {
@Id
@GeneratedValue
private Long id;
private String name;
@Type(type = "json")
@Column(columnDefinition = "jsonb")
private Map<String, Object> preferences;
}
Key Points:
@TypeDef registers a reusable JSON type@Column(columnDefinition = "jsonb") ensures PostgreSQL uses JSONBObjectMapper or converters{
"theme":"dark",
"language":"en",
"notifications":true
}
MapWhen the JSON structure is known or stable, using a custom POJO is the best practice instead of Map<String, Object>.
POJO Example
publicclassUserPreferences {
private String theme;
private String language;
privateboolean notifications;
// getters and setters
}
Entity Field Mapping
@Type(type = "json")
@Column(columnDefinition = "jsonb")
private UserPreferences preferences;
@Converter (JPA Standard Approach)The @Converter approach is the pure JPA-standard way to store JSON in the database.
It works with any JPA provider (Hibernate, EclipseLink, etc.), but offers less type safety compared to Hibernate JSON types.
JSON Converter Implementation
@Converter
publicclassJsonConverterimplementsAttributeConverter<Object, String> {
privatefinalObjectMappermapper=newObjectMapper();
@Override
public StringconvertToDatabaseColumn(Object attribute) {
try {
return mapper.writeValueAsString(attribute);
}catch (Exception e) {
thrownewRuntimeException("Error converting object to JSON", e);
}
}
@Override
public ObjectconvertToEntityAttribute(String dbData) {
try {
return mapper.readValue(dbData, Object.class);
}catch (Exception e) {
thrownewRuntimeException("Error converting JSON to object", e);
}
}
}
Using the Converter in Entity
@Convert(converter = JsonConverter.class)
@Column(columnDefinition = "jsonb")
private Object metadata;
Pros
Cons
ObjectPostgreSQL Native Query Example
@Query(
value = "SELECT * FROM users WHERE preferences ->> 'language' = 'en'",
nativeQuery = true
)
List<User>findEnglishUsers();
->>)CREATE INDEX idx_users_preferences
ON usersUSING GIN (preferences);
👉 Without proper indexing, JSONB queries can become a performance bottleneck.
JSON fields integrate cleanly with DTO projections, keeping APIs efficient and secure:
publicinterfaceUserView {
StringgetName();
UserPreferencesgetPreferences();
}
Auditing annotations work naturally alongside JSON fields:
@LastModifiedDate
private LocalDateTime updatedAt;
@Column(columnDefinition = "jsonb")
private Map<String, Object> changeLog;
Useful For
| Aspect | JSON / JSONB | Relational Columns |
|---|---|---|
| Schema flexibility | High – supports dynamic, schema-less data | Low – fixed schema, changes require migrations |
| Query performance | Medium → High when indexed (GIN indexes for JSONB) | High – optimized for traditional SQL queries |
| Type safety | Medium – may require custom DTOs or Maps | High – enforced by database types and JPA mapping |
| Best use case | Flexible attributes, user preferences, metadata, dynamic configs | Core business fields, transactional data, relationships |
Map<String, Object> everywhereAdvanced JSON / JSONB mapping enables Spring Boot applications to handle flexible and evolving data models without sacrificing maintainability.
By using JSONB, Hibernate Types, proper indexing, and typed Java objects, you achieve the best balance of performance, flexibility, and clarity—making JSON mapping a powerful tool for modern, enterprise-grade applications.