Java 如果开头的驼峰式单词只有一个字母长,为什么 Jackson 2 无法识别第一个大写字母?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30205006/
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-08-11 09:19:23  来源:igfitidea点击:

Why does Hymanson 2 not recognize the first capital letter if the leading camel case word is only a single letter long?

javajsonspringspring-mvcHymanson

提问by Hazok

I'm using Spring 4 MVC with Hymanson 2 for my service. For one of the operations I have a request object that has an attribute where the leading camel case word this is only one letter in length:

我将 Spring 4 MVC 与 Hymanson 2 用于我的服务。对于其中一项操作,我有一个请求对象,该对象具有一个属性,其中前导驼峰式单词的长度只有一个字母:

private String aLogId;

This class has the appropriately named getters and setters:

此类具有适当命名的 getter 和 setter:

public String getALogId() { return aLogId; }
public void setALogId(String aLogId) { this.aLogId = aLogId; }

However, when I attempt to post a request to this service using the corresponding JSON property:

但是,当我尝试使用相应的 JSON 属性向此服务发布请求时:

{"aLogId":"This is a log id"}

I'm receiving a 500 response from the Spring framework saying the field is not recognized and my controller class is never called:

我收到来自 Spring 框架的 500 响应,说该字段无法识别并且我的控制器类从未被调用:

Could not read JSON: Unrecognized field "aLogId" (class

无法读取 JSON:无法识别的字段“aLogId”(类

However, when I change the "L" to lower case, the request is deserialized as expected and my controller class is hit:

但是,当我将“L”更改为小写时,请求会按预期反序列化并且我的控制器类被命中:

{"alogId":"This is a log id"}

Why does Hymanson expect the "L" to be lower case when it is obviously the second word in the camel case convention for the attribute and intended to be in upper case? Is it because the first word is only a single letter long?

为什么Hyman逊希望“L”是小写的,而它显然是骆驼大小写约定中属性的第二个单词并打算大写?是不是因为第一个单词只有一个字母长?

There are other attributes in the request object where the first word is more than one letter and those attributed don't face this same issue with the mismatch in case.

请求对象中还有其他属性,其中第一个单词超过一个字母,并且这些属性不会遇到同样的问题,以防万一。

采纳答案by jbarrueta

The problem you are seeing is due to the fact that Hymanson uses Java Bean naming conventions, to figure it out the the Json properties in a Java class.

您看到的问题是由于 Hymanson 使用 Java Bean 命名约定来确定 Java 类中的 Json 属性。

Here is a referenceof the specific problem you see, the recommendation is not to capitalize none of the first two letters in your field. If you use an IDE like IntelliJ or eclipse and let the IDE generate the setters for you, you will notice the same "behavior" occurs, you will end up with the following methods:

下面是一个参考,你看到的具体问题,建议不大写没有在你的领域的前两个字母。如果您使用 IntelliJ 或 eclipse 等 IDE 并让 IDE 为您生成 setter,您会注意到发生了相同的“行为”,您最终会得到以下方法:

public void setaLogId(String aLogId) {
    this.aLogId = aLogId;
}

public String getaLogId() {
    return aLogId;
}

Hence, when you change the "L" to lower case Hymanson was able to figure it out the field you wanted to map.

因此,当您将“L”更改为小写时,Hymanson 能够找出您想要映射的字段。

Having said the above, you still have the alternative to use the "aLogId" field name and make Hymanson work all you have to do is use the @JsonPropertyannotation with the aLogIdin it.

综上所述,您仍然可以选择使用“aLogId”字段名称并使 Hymanson 工作,您所要做的就是使用其中的@JsonProperty注释aLogId

@JsonProperty("aLogId")
private String aLogId;

The following test code is to show how this will work:

下面的测试代码是为了展示这将如何工作:

import com.fasterxml.Hymanson.annotation.JsonProperty;
import com.fasterxml.Hymanson.databind.ObjectMapper;

public class Test {

    @JsonProperty("aLogId")
    private String aLogId;

    public void setaLogId(String aLogId) {
        this.aLogId = aLogId;
    }

    public String getaLogId() {
        return aLogId;
    }

    public static void main(String[] args) {

        ObjectMapper objectMapper = new ObjectMapper();

        Test test = new Test();

        test.setaLogId("anId");

        try {
            System.out.println("Serialization test: " + objectMapper.writeValueAsString(test));


            String json = "{\"aLogId\":\"anotherId\"}";

            Test anotherTest = objectMapper.readValue(json, Test.class);

            System.out.println("Deserialization test: " +anotherTest.getaLogId());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

The output of the test is:

测试的输出是:

Serialization test: {"aLogId":"anId"}

Serialization test: {"aLogId":"anId"}

Deserialization test: anotherId

Deserialization test: anotherId

回答by Geoff Alexander

My understanding is that Hymanson uses by default its own naming convention, which is very close, but not exactly the same, to the Java Bean naming convention. A MapperFeature option, MapperFeature.USE_STD_BEAN_NAMING, was added in Hymanson 2.5.0 to tell Hymanson to use the Java Bean naming convention -- see Hymanson Issue 653. For backward compatibility, the default value for MapperFeature.USE_STD_BEAN_NAMING is false.

我的理解是 Hymanson 默认使用自己的命名约定,这与 Java Bean 命名约定非常接近,但并不完全相同。在 Hymanson 2.5.0 中添加了 MapperFeature 选项 MapperFeature.USE_STD_BEAN_NAMING 以告诉 Hymanson 使用 Java Bean 命名约定 - 请参阅Hymanson Issue 653。为了向后兼容,MapperFeature.USE_STD_BEAN_NAMING 的默认值为 false。

回答by rupanjan

This has worked for me; @JsonProperty annotation on getters!

这对我有用;@JsonProperty 上的 getter 注释!

import com.fasterxml.Hymanson.annotation.JsonProperty;

public class PaytmRequestJson {
    private String ORDERID;
    private String MID;
    private String CHECKSUMHASH;

    @JsonProperty("ORDERID")
    public String getORDERID() {
        return ORDERID;
    }

    public void setORDERID(String ORDERID) {
        this.ORDERID = ORDERID;
    }

    @JsonProperty("MID")
    public String getMID() {
        return MID;
    }

    public void setMID(String MID) {
        this.MID = MID;
    }

    @JsonProperty("CHECKSUMHASH")
    public String getCHECKSUMHASH() {
        return CHECKSUMHASH;
    }

    public void setCHECKSUMHASH(String CHECKSUMHASH) {
        this.CHECKSUMHASH = CHECKSUMHASH;
    }
}

回答by TheOperator

@JsonPropertyas suggested by the current answer has the disadvantage that you need to repeat it for every single property, and that it's invasive (you need to change the class being mapped).

@JsonProperty正如当前答案所建议的那样,缺点是您需要为每个属性重复它,并且它是侵入性的(您需要更改被映射的类)。

A more general approach is to provide a custom Property Naming Strategy:

更通用的方法是提供自定义属性命名策略

Java:

爪哇

public class CustomSnakeCase extends PropertyNamingStrategy.PropertyNamingStrategyBase {
    private static final Pattern REGEX = Pattern.compile("[A-Z]");

    @Override
    public String translate(String input) {
        if (input == null)
            return input; // garbage in, garbage out

        if (!input.isEmpty() && Character.isUpperCase(input.charAt(0)))
            input = input.substring(0, 1).toLowerCase() + input.substring(1);

        return REGEX.matcher(input).replaceAll("_
class CustomSnakeCase : PropertyNamingStrategy.PropertyNamingStrategyBase() {
    private companion object {
        val REGEX = Regex("[A-Z]")
    }

    override fun translate(input: String?) =
        input?.decapitalize()?.replace(REGEX, "_
new ObjectMapper()
    .setPropertyNamingStrategy(new CustomSnakeCase())
    .enable(MapperFeature.USE_STD_BEAN_NAMING)
")?.toLowerCase() }
").toLowerCase(); } }

Kotlin:

科特林:

camelCase      snake_case
----------------------------
simple         simple
a              a
sepaRated      sepa_rated
iOException    i_o_exception
xOffset        x_offset
theWWW         the_w_w_w
sepaRated32    sepa_rated32
sepa32Rated    sepa32_rated

Usage:

用法:

##代码##

Note:The implementation I provide above assumes that input is camelCase(no uppercase beginning). USE_STD_BEAN_NAMINGis needed to handle 1-character prefixes such as aFieldconsistely.

注意:我上面提供的实现假设输入是camelCase(没有大写开头)。USE_STD_BEAN_NAMING需要处理 1 个字符的前缀,例如aFieldconsistely。

The implementation provides the following mapping, you might adjust it according to your needs:

该实现提供了以下映射,您可以根据需要对其进行调整:

##代码##

回答by Garvit Jain

I got the same problem on Kotlin. Resolved by using Use the @JsonProperty annotation to the accessor methods.

我在Kotlin上遇到了同样的问题。通过对访问器方法使用 @JsonProperty 注释来解决。

For example: @get:JsonProperty("ID") val id: String = ""

例如:@get:JsonProperty("ID") val id: String = ""