简体   繁体   English

Jackson ObjectMapper 大写/小写问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM