0

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>
  • Just curious why you want it ordered. The [json spec](https://www.json.org/json-en.html) says objects are unordered, so no parser of them should be changing behaviour based on the order. – BeUndead Sep 26 '21 at 01:18
  • 1
    You are absolutely right! Thank you! (below I answered in more detail in another comment on the reasons). – Сергей Аблаев Sep 26 '21 at 16:02

1 Answers1

2

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:

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Wow! Bravo! Your conclusions are absolutely correct. Indeed, our code works with any sort order. This requirement was requested by operators that look at the jsonb type data in the column on SQL. I understand that the analyst's requirements violate the JSON conventions, but I decided to look for a possible solution. Thank you for such a compelling analysis and links to sources! – Сергей Аблаев Sep 26 '21 at 16:32