java Jackson ObjectMapper 大写/小写问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26744885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:31:52  来源:igfitidea点击:

Hymanson ObjectMapper upper/lower case issues

javajsonHymanson

提问by Barni

When I serialize/deserialize any object, all field names are converted to lower case. Is there any configuration to set that makes Hymanson keep the field names exactly as they are? Both for serializing and deserializing?

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

(I know about @JsonProperty, but this does not seems to be right, since what I need is just for Hymanson to respect what already exists)

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

My test code:

我的测试代码:

import java.io.Serializable;

import com.fasterxml.Hymanson.databind.DeserializationFeature;
import com.fasterxml.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.databind.PropertyNamingStrategy;
import com.fasterxml.Hymanson.databind.SerializationFeature;
import com.fasterxml.Hymanson.databind.cfg.MapperConfig;
import com.fasterxml.Hymanson.databind.introspect.AnnotatedField;
import com.fasterxml.Hymanson.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. Here it is:

感谢@BlueLettuce16,我设法构建了一个“改进”版本的PropertyNamingStrategy. 这里是:

import java.lang.reflect.Modifier;

import com.fasterxml.Hymanson.databind.PropertyNamingStrategy;
import com.fasterxml.Hymanson.databind.cfg.MapperConfig;
import com.fasterxml.Hymanson.databind.introspect.AnnotatedField;
import com.fasterxml.Hymanson.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].*");
    }

}

采纳答案by BlueLettuce16

I think that this is the solution (using custom PropertyNamingStrategy):

我认为这是解决方案(使用自定义 PropertyNamingStrategy):

import com.fasterxml.Hymanson.databind.PropertyNamingStrategy;
import com.fasterxml.Hymanson.databind.cfg.MapperConfig;
import com.fasterxml.Hymanson.databind.introspect.AnnotatedField;
import com.fasterxml.Hymanson.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.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.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

个人

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

回答by Bobby

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.

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

回答by Ethan

Even though @JsonPropertydoesn't work, I was able to use @JsonSetterand @JsonGetterto 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”。

回答by Leos Literak

You can configure Hymanson to be case sensitivity tolerant:

您可以将 Hymanson 配置为区分大小写:

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致敬