[英]Jackson ObjectMapper upper/lower case issues
When I serialize/deserialize any object, all field names are converted to lower case.当我序列化/反序列化任何对象时,所有字段名称都转换为小写。 Is there any configuration to set that makes Jackson keep the field names exactly as they are?是否有任何配置可以让 Jackson 保持字段名称的原样? Both for serializing and deserializing?用于序列化和反序列化?
(I know about @JsonProperty, but this does not seems to be right, since what I need is just for Jackson to respect what already exists) (我知道@JsonProperty,但这似乎不对,因为我需要的只是让杰克逊尊重已经存在的东西)
My test code:我的测试代码:
import java.io.Serializable;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class Test {
static class Example implements Serializable {
private String Test;
private String ABC;
private String XyZ;
public String getTest() { return Test; }
public void setTest(String test) { Test = test; }
public String getABC() { return ABC; }
public void setABC(String abc) { ABC = abc; }
public String getXyZ() { return XyZ; }
public void setXyZ(String xyz) { XyZ = xyz; }
}
static class MyPropertyNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(defaultName);
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
private String convert(String input) {
return input;
}
}
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(new MyPropertyNamingStrategy())
.enable(SerializationFeature.INDENT_OUTPUT)
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
//From OBJECT to JSON
Example ex = new Example();
ex.setTest("1");
ex.setABC("2");
ex.setXyZ("3");
System.out.println(objectMapper.writeValueAsString(ex));
//FROM JSON to OBJECT
String jsonString = "{ \"Test\":\"0\", \"ABC\":\"1\", \"XyZ\":\"2\" }";
Example fEx = objectMapper.readValue(jsonString, Example.class);
}
}
Thanks to @BlueLettuce16, I have managed to build an 'improved' version of the PropertyNamingStrategy
.感谢@BlueLettuce16,我设法构建了一个“改进”版本的PropertyNamingStrategy
。 Here it is:这里是:
import java.lang.reflect.Modifier;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class CustomPropertyNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convertForField(defaultName);
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convertForMethod(method, defaultName);
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convertForMethod(method, defaultName);
}
private String convertForField(String defaultName) {
return defaultName;
}
private String convertForMethod(AnnotatedMethod method, String defaultName) {
if (isGetter(method)) {
return method.getName().substring(3);
}
if (isSetter(method)) {
return method.getName().substring(3);
}
return defaultName;
}
private boolean isGetter(AnnotatedMethod method) {
if (Modifier.isPublic(method.getModifiers()) && method.getGenericParameterTypes().length == 0) {
if (method.getName().matches("^get[A-Z].*") && !method.getGenericReturnType().equals(void.class))
return true;
if (method.getName().matches("^is[A-Z].*") && method.getGenericReturnType().equals(boolean.class))
return true;
}
return false;
}
private boolean isSetter(AnnotatedMethod method) {
return Modifier.isPublic(method.getModifiers()) && method.getGenericReturnType().equals(void.class) && method.getGenericParameterTypes().length == 1
&& method.getName().matches("^set[A-Z].*");
}
}
I've had the same problem. 我遇到了同样的问题。
This is my solution: 这是我的解决方案:
public class MyNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return field.getName();
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method, defaultName);
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method, defaultName);
}
private String convert(AnnotatedMethod method, String defaultName) {
Class<?> clazz = method.getDeclaringClass();
List<Field> flds = FieldUtils.getAllFieldsList(clazz);
for (Field fld : flds) {
if (fld.getName().equalsIgnoreCase(defaultName)) {
return fld.getName();
}
}
return defaultName;
}
}
In this case you will get the exact name of the property, and will not have to depend on the correct names of the methods. 在这种情况下,您将获得属性的确切名称,而不必依赖于方法的正确名称。
I think that this is the solution (using custom PropertyNamingStrategy): 我认为这是解决方案(使用自定义PropertyNamingStrategy):
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class MyPropertyNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(field.getName());
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
private String convert(String input) {
return input.substring(3);
}
}
Test 测试
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.io.StringWriter;
public class MyPropertyNamingStrategyTest {
public static void main(String[] args) {
PrivatePerson privatePerson = new PrivatePerson();
privatePerson.setFirstName("John");
privatePerson.setLastName("Smith");
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
StringWriter sw = new StringWriter();
try {
mapper.writeValue(sw, privatePerson);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(sw.toString());
}
}
PrivatePerson PrivatePerson
public class PrivatePerson {
private String firstName;
private String lastName;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
}
You can configure Jackson to be case sensitivity tolerant: 您可以将Jackson配置为区分大小写:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
Cudos to https://stackoverflow.com/a/32842962/1639556 感谢https://stackoverflow.com/a/32842962/1639556
Even though @JsonProperty
doesn't work, I was able to use @JsonSetter
and @JsonGetter
to map capitalized json field names. 即使@JsonProperty
不起作用,我也能够使用@JsonSetter
和@JsonGetter
来映射大写的json字段名称。
@JsonSetter("ABC")
public void setABC(String ABC) {
this.ABC= ABC;
}
Spring will now serialize the object field as "ABC" and not "abc". Spring现在将对象字段序列化为“ABC”而不是“abc”。
Using @JsonProperty annotation.使用@JsonProperty 注释。 It work well它运作良好
Example例子
@JsonProperty("Code")
private String Code;
@JsonProperty("Message")
private String Message;
*Created a own class for PropertyNamingStrategy- As per Answer 7 Working fine * *为 PropertyNamingStrategy 创建了一个自己的类 - 根据答案 7 工作正常 *
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class MyPropertyNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(field.getName());
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
private String convert(String input) {
return input.substring(3);
}
}
*And I have my POJO class - the Payload Class:*
package orderCreateAPI;
import java.util.ArrayList;
public class Payload {
OrderInfo OrderInfo;
ArrayList<orderCreateAPI.ShipmentInfo> ShipmentInfo;
public Payload(OrderInfo order, ArrayList<orderCreateAPI.ShipmentInfo> shipInfo){
this.OrderInfo =order;
this.ShipmentInfo = shipInfo;
}
public OrderInfo getOrderInfo() {
return OrderInfo;
}
public void setOrderInfo(OrderInfo orderInfo) {
OrderInfo = orderInfo;
}
public ArrayList<orderCreateAPI.ShipmentInfo> getShipmentInfo() {
return ShipmentInfo;
}
public void setShipmentInfo(ArrayList<orderCreateAPI.ShipmentInfo> shipmentInfo) {
ShipmentInfo = shipmentInfo;
}
}
*The execution class:*
public class TC1_CreateOrder extends orderCreateRequest{
@Test
public static void TC1_CreateOrder() throws JsonProcessingException,JsonMappingException,IOException {
// throws JsonParseException,JsonMappingException,IOException
//Data fetch
ArrayList<OrderReferences> orRef = new ArrayList<OrderReferences>();
orRef.add(new OrderReferences("BM","IFC"));
ArrayList<OrderItem> orItem = new ArrayList<OrderItem>();
orItem.add(new OrderItem("AOTEST1001","60111"));
ShipperInfo ship = new ShipperInfo("URBN","URBN PA DC");
ArrayList<ShipmentInfo> ShipInfo = new ArrayList<ShipmentInfo>();
ShipInfo.add(new ShipmentInfo("ASTEST1001","RCVD"),ship, orItem));
ConsigneeInfo ConsigneeInfo = new ConsigneeInfo("Green Mile","133 Avenue");
OrderInfo OrderInfo = new OrderInfo("AOTEST1001", "2021-09-03T",orRef, ConsigneeInfo);
Payload p = new Payload(OrderInfo,ShipInfo);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy());
StringWriter s = new StringWriter();
try {
mapper.writeValue(s, p);
} catch (IOException e) {
e.printStackTrace();
}
}
}
response body before: -Wrong properties* { "orderInfo": { "orderNumber": "AOTEST1010", "orderCreatedDate": "2021-09-03T00:00:00.000Z" } }之前的响应正文:-错误的属性* { "orderInfo": { "orderNumber": "AOTEST1010", "orderCreatedDate": "2021-09-03T00:00:00.000Z" } }
response body after: -correct properties* { "OrderInfo": { "OrderNumber": "AOTEST1010", "OrderCreatedDate": "2021-09-03T00:00:00.000Z" } }响应正文之后:-正确的属性* { "OrderInfo": { "OrderNumber": "AOTEST1010", "OrderCreatedDate": "2021-09-03T00:00:00.000Z" } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.