Почему имена полей в формате json для встроенной сущности надо указывать в lowercase?

Имею сущность:

@Getter
@Setter
@ToString
@Entity
@Table(name = "contact_channel")
public class ContactChannel {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "channel_name")
    private String channelName;

    @ElementCollection
    @CollectionTable(name = "contact", joinColumns = @JoinColumn(name = "contact_channel_id"))
    private List<Contact> contact = new ArrayList<>();
}

Встроенную сущность:

@Getter
@Setter
@ToString
@Embeddable
public class Contact {
    @Column(name = "c_type")
    private String cType;

    @Column(name = "c_value")
    private String cValue;
}

Контроллер:

    @PostMapping("/save")
    public ContactChannel save(@RequestBody ContactChannel contactChannel) {
        return contactChannelRepository.save(contactChannel);
    }

Когда передаю json с именами полей как в сущностях:

{
  "id": 31,
  "channelName": "test_f2fbd4301322",
  "contact": [
    {
      "cType": "test_0e2d4fca0ea9",
      "cValue": "test_d2587c69ac60"
    }
  ]
}

То уже в контроллере получаю в полях cType и cValue значение null.

Когда передаю json с именами полей у встроенной сущности в lowercase:

{
  "id": 31,
  "channelName": "test_f2fbd4301322",
  "contact": [
    {
      "ctype": "test_0e2d4fca0ea9",
      "cvalue": "test_d2587c69ac60"
    }
  ]
}

то поля заполняются корректно.
Почему так происходит? И можно ли сделать так чтобы использовать имена полей с учетом регистра?


Ответы (2 шт):

Автор решения: Михаил Ребров

Странное поведение - лично мне такое не встречалось и поля всегда использовались регистрозависимые.


Можно попробовать явно задать имя поля, которое будет использоваться при сериализации/десериализации.

Для этого над полем необходимо проставить аннотацию, в которой можно указать название поля.

В зависимости от используемых адаптеров Jackson / Gson они могут отличаться

  • Jackson использует аннотацию @JsonProperty("___")
  • Gson использует аннотацию @SerializedName("___")

Jackson
Насколько я понимаю у Вас должен использоваться именно он

@Getter
@Setter
@ToString
@Embeddable
public class Contact {
    @JsonProperty("cType")
    @Column(name = "c_type")
    private String cType;

    @JsonProperty("cValue")
    @Column(name = "c_value")
    private String cValue;
}

Gson

@Getter
@Setter
@ToString
@Embeddable
public class Contact {
    @SerializedName("cType")
    @Column(name = "c_type")
    private String cType;

    @SerializedName("cValue")
    @Column(name = "c_value")
    private String cValue;
}
→ Ссылка
Автор решения: XelaNimed

Спецификация ECMA-404 не накладывает ограничения на регистр, уникальность или порядок следования ключей. Это зависит от конкретной реализации API или спецификации. Именование же ключей JSON в нижнем регистре де-факто является общепринятым стандартом. Если к Вашему вопросу, то у каждой библиотеки де/-сериализатора имеется конфигурация, которая позволяет указать различные параметры сериализации/-десериализации, правил обработки отсутствующих значений и т.д.. Если мы говорим о Jackson, то для этого можно использовать метод ObjectMapper.configure:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

У MapperFeature ещё много параметров, которые можно сконфигурировать. Вариант с декорированием полей необходимыми именами тоже рабочий, но может быть утомительным при:

  • большом количестве полей
  • переименовании кода
  • невозможности изменить код классов

Ссылки по теме:

→ Ссылка