Почему имена полей в формате 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;
}
Спецификация ECMA-404 не накладывает ограничения на регистр, уникальность или порядок следования ключей. Это зависит от конкретной реализации API или спецификации. Именование же ключей JSON в нижнем регистре де-факто является общепринятым стандартом.
Если к Вашему вопросу, то у каждой библиотеки де/-сериализатора имеется конфигурация, которая позволяет указать различные параметры сериализации/-десериализации, правил обработки отсутствующих значений и т.д.. Если мы говорим о Jackson, то для этого можно использовать метод ObjectMapper.configure:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
У MapperFeature ещё много параметров, которые можно сконфигурировать. Вариант с декорированием полей необходимыми именами тоже рабочий, но может быть утомительным при:
- большом количестве полей
- переименовании кода
- невозможности изменить код классов
Ссылки по теме:
- ECMA-404 2nd Edition
- com.fasterxml.jackson.databind.ObjectMapper.configure(MapperFeature f, boolean state)
- com.fasterxml.jackson.databind.ObjectMapper.configure(SerializationFeature f, boolean state)
- com.fasterxml.jackson.databind.ObjectMapper.configure(DeserializationFeature f, boolean state)