杰克逊对象映射器大写/小写问题

2022-09-02 01:02:49

当我序列化/反序列化任何对象时,所有字段名称都转换为小写。是否有任何要设置的配置可以使 Jackson 保持字段名称的原样?是否同时用于序列化和反序列化?

(我知道@JsonProperty,但这似乎不对,因为我需要的只是让杰克逊尊重已经存在的东西)

我的测试代码:

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);
    }   

}

多亏了@BlueLettuce16,我设法构建了.在这里:PropertyNamingStrategy

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].*");
    }

}

答案 1

即使不起作用,我也能够使用和映射大写的json字段名称。@JsonProperty@JsonSetter@JsonGetter

@JsonSetter("ABC")
public void setABC(String ABC) {
    this.ABC= ABC;
}

Spring 现在将对象字段序列化为“ABC”而不是“abc”。


答案 2

我也有同样的问题。

这是我的解决方案:

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;
    }
}

在这种情况下,您将获得属性的确切名称,而不必依赖于方法的正确名称。