Hibernate jsonb type: Is it possible to change the order of the default JSON fields to a different one?

1.2k Views Asked by At

I have a project with Spring Boot with Hibernate. For json field use annotations like @Type(type = "jsonb"), and definition Hibernate ORM extra Types: "com.vladmihalcea, hibernate-types-52"

Its work correctly. But Is it possible to change the order of the default fields to a different one? Like “@JsonPropertyOrder”. (This annotation doesn’t work here).

For example – the code below writes the jsonb to PostgreSQL:

Result – birthDate inside full name: {“lastName”: “some lastName”, “birthDate”: “01.01.1985”, “firstName”: “some firstName”, “middleName”: “some middlname”, “personDocument”: null}

I need: {“lastName”: “some lastName”, “firstName”: “some firstName”, “middleName”: “some middlname”, “birthDate”: “01.01.1985”, “personDocument”: null}

———–source model class————–

@JsonPropertyOrder(  //This annotation not work :(
{“lastName”, “firstName”, “middleName”, “birthDate”, “personDocument”})

public class PersonInfo implements Serializable {

private static final long serialVersionUID = 8604200400882367977L;

@JsonSerialize(using = SnilsSerializer.class)
private String lastName;
private String firstName;
private String middleName;
private PersonInfoDocument personDocument;
@JsonSerialize(using = LocalDateSerializer.class)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy")
private LocalDate birthDate;
}

-----------Entity class---------------------

@Data
@Builder
@Entity
@Table(name = "CO_PERSONS")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@ToString(exclude = {"co", "personInfo"})
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person extends AuditableModel<Long> {
    private static final long serialVersionUID = 3903875373255655212L;
    @Id
    @SequenceGenerator(name = "co_persons_cp_id_seq",
                       sequenceName = "co_persons_cp_id_seq",
                       allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
                    generator = "co_persons_cp_id_seq")
    @Column(name = "cp_id", updatable = false)
    private Long id;

    @Type(type = "jsonb")
    @Column(name = "cp_individual_json", columnDefinition = "jsonb")
    private PersonInfo personInfo;

--------------pom dependency-------------

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

There are 1 best solutions below

1
On BEST ANSWER

It should not matter what the order of the JSON attributes is. The JSON specs state clearly that JSON object attributes are unordered. If your code is placing significance on the (unspecified) order of the attributes in the serialization, it is misusing JSON.

So the most correct solution to your problem is to change your application so that it doesn't depend on the JSON attribute order.

(In your example, I can't imagine why the order of the attributes has semantic significance. So, my guess is that you are rendering the JSON to some other form (e.g. HTML or CSV) where the order has some significance to people ... or software. In such cases, the best solution is to specify the ordering you want at the point where you are rendering.)

There are hacky solutions to this that work for some JSON parsers. For example, some parsers allow you to provide provide your own Map implementation. So, if you used a LinkedHashMap when serializing and deserializing, and you originally added the attributes in a specific order, the insertion order of the attributes should be preserved through serialization and deserialization.

However, I don't know if there is a hacky solution that works with "jsonb" serialization. So you might need to do the serialization "by hand" rather than using @JsonSerialize.


If you are doing this because you have been told to implement some requirements that prescribe a specific order for the JSON attributes, then that requirements specification is broken. You should push back. Point out that what they have asked for is NOT JSON. If they need things to be ordered in JSON ... they should specify a JSON array.


References: