Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson是否将属性的第二个字符反序列化为小写_Java_Json_Jackson_Deserialization_Fasterxml - Fatal编程技术网

Java Jackson是否将属性的第二个字符反序列化为小写

Java Jackson是否将属性的第二个字符反序列化为小写,java,json,jackson,deserialization,fasterxml,Java,Json,Jackson,Deserialization,Fasterxml,我们在服务代码中定义了一个模型- @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public class SomeData { public boolean tnAvailable; @NonNull public String sTempChange; public boolean isTnAvailable() { return faAvailable; }

我们在服务代码中定义了一个模型-

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class SomeData {

    public boolean tnAvailable;

    @NonNull
    public String sTempChange;

    public boolean isTnAvailable() {
       return faAvailable;
    }

    public void setTnAvailable(boolean faAvailable) {
        this.faAvailable = faAvailable;
    }

    @Nonnull
    public String getSTempChange() {
        return sTempChange;
    }

    public void setSTempChange(@Nonnull String sTempChange) {
        this.sTempChange = sTempChange;
    }

}
当查询包含上述响应模型的api时,我们得到的响应如下-

"someData": {
    "tnAvailable": true,
    "stempChange": "trial_001"
}
让我们惊讶的是响应属性中的
stempChange
(注意小写
t
)而不是
stempChange

怀疑原因是Jackson com.fasterxml.Jackson.core:Jackson core:2.5.2在API调用期间序列化和反序列化对象,因为我们没有使用任何其他getter setter-ot包装器更改属性。 为什么会发生这种情况?序列化/反序列化是寻找这种情况的正确方向吗


编辑——摘自@Windle的评论,试图解释这里的不同之处。我再次重申“这个问题虽然与相同的情况有很大关系。但是我也期待着用fasterxml实现和编写文档的原因。”

是的,它看起来在方法名称上有点混乱。您可以使用@JsonGetter注释强制序列化名称

@JsonGetter("sTempChange")
public String getSTempChange() {
    return sTempChange;
}

是的,它看起来在方法名上有点混乱。您可以使用@JsonGetter注释强制序列化名称

@JsonGetter("sTempChange")
public String getSTempChange() {
    return sTempChange;
}

处理getter/setter中的多个前导大写字母(如“getURL()”或“getFName()”)。 默认情况下,Jackson只需将所有前导大写字母小写,给出“url”和“fname”。 但是,如果您启用MapperFeature.USE_STD_BEAN_NAMING(在Jackson 2.5中添加),它将遵循Java BEAN命名约定所做的操作,即只使用小写字母和大写字母;如果找到多个,则不执行任何操作。
这将导致属性“URL”和“FName”。

处理getter/setter中的多个前导大写字母(如“getURL()”或“getFName()”)。 默认情况下,Jackson只需将所有前导大写字母小写,给出“url”和“fname”。 但是,如果您启用MapperFeature.USE_STD_BEAN_NAMING(在Jackson 2.5中添加),它将遵循Java BEAN命名约定所做的操作,即只使用小写字母和大写字母;如果找到多个,则不执行任何操作。
这将导致属性“URL”和“FName”。

当我第一次尝试您的
SomeData
类并对其进行序列化时,我得到了以下结果:

{"tnAvailable":true,"sTempChange":"trial_000","stempChange":"trial_000"}
这意味着jackson不会将您的getter/setter与sTempChange属性匹配,它们被视为不同的属性。为我的映射器添加以下配置后,我能够重现您的案例:

    ObjectMapper objectMapper = new ObjectMapper();

    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
    objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
    objectMapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.ANY);
    objectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY);
现在,出现错误的原因是Jackson使用了自己的bean实用程序(
com.fasterxml.Jackson.databind.util.BeanUtil
)实现,该实现在处理字段、getter和setter类时使用(由
com.fasterxml.Jackson.databind.introspect.POJOPropertiesCollector
完成)当实例被序列化/反序列化时。感兴趣的方法是
okNameForSetter
okNameForSetter
。在这些方法中,根据
MapperFeature,还使用了另外两种方法。使用\u STD\u BEAN\u NAMING
(在所有方法中,它都在
stdNaming
参数中传递)。这两种方法的使用方式如下:

return stdNaming
                ? stdManglePropertyName(name, prefix.length())
                : legacyManglePropertyName(name, prefix.length());
stdManglePropertyName
遵循第8.8节中的Java Beans规范,而
legacyManglePropertyName
没有,并且在Jackson 2.5之前的版本中使用

现在,在通过此方法运行getter和setter方法名称之后,您设置了
MapperFeature.USE\u STD\u BEAN\u NAMING
,您的
sTempChange
属性的getter/setter命名错误。它应该是
getsTempChange
(小写)和
getsTempChange
(同样小写)来正确序列化和反序列化
SomeData
类的实例

最后,这里是一些测试代码:

import com.fasterxml.jackson.databind.ObjectMapper;


public class Test {

static class SomeData {

    public boolean tnAvailable;

    public String sTempChange;

    public String getsTempChange() {
        return sTempChange;
    }

    public void setsTempChange(String sTempChange) {
        this.sTempChange = sTempChange;
    }

    public boolean isTnAvailable() {
        return tnAvailable;
    }

    public void setTnAvailable(boolean tnAvailable) {
        this.tnAvailable = tnAvailable;
    }

}

public static void main(String[] args) {

    ObjectMapper objectMapper = new ObjectMapper();

//  objectMapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true);

    SomeData someData = new SomeData();
    someData.setsTempChange("trial_000");
    someData.setTnAvailable(true);

//  objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
//  objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
//  objectMapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.ANY);
//  objectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY);

    try {
        System.out.println("Serialize: " + objectMapper.writeValueAsString(someData));

        String json = "{ \"tnAvailable\": false, \"sTempChange\": \"trial_001\" }";

        SomeData anotherData = objectMapper.readValue(json, SomeData.class);

        System.out.println("Deserialize: " + anotherData.isTnAvailable() + ", " + anotherData.getsTempChange());

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

}

}

当我第一次尝试您的
SomeData
类并将其序列化时,我得到了以下结果:

{"tnAvailable":true,"sTempChange":"trial_000","stempChange":"trial_000"}
这意味着jackson不会将您的getter/setter与sTempChange属性匹配,它们被视为不同的属性。为我的映射器添加以下配置后,我能够重现您的案例:

    ObjectMapper objectMapper = new ObjectMapper();

    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
    objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
    objectMapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.ANY);
    objectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY);
现在,出现错误的原因是Jackson使用了自己的bean实用程序(
com.fasterxml.Jackson.databind.util.BeanUtil
)实现,该实现在处理字段、getter和setter类时使用(由
com.fasterxml.Jackson.databind.introspect.POJOPropertiesCollector
完成)当实例被序列化/反序列化时。感兴趣的方法是
okNameForSetter
okNameForSetter
。在这些方法中,根据
MapperFeature,还使用了另外两种方法。使用\u STD\u BEAN\u NAMING
(在所有方法中,它都在
stdNaming
参数中传递)。这两种方法的使用方式如下:

return stdNaming
                ? stdManglePropertyName(name, prefix.length())
                : legacyManglePropertyName(name, prefix.length());
stdManglePropertyName
遵循第8.8节中的Java Beans规范,而
legacyManglePropertyName
没有,并且在Jackson 2.5之前的版本中使用

现在,在通过此方法运行getter和setter方法名称之后,您设置了
MapperFeature.USE\u STD\u BEAN\u NAMING
,您的
sTempChange
属性的getter/setter命名错误。它应该是
getsTempChange
(小写)和
getsTempChange
(同样小写)来正确序列化和反序列化
SomeData
类的实例

最后,这里是一些测试代码:

import com.fasterxml.jackson.databind.ObjectMapper;


public class Test {

static class SomeData {

    public boolean tnAvailable;

    public String sTempChange;

    public String getsTempChange() {
        return sTempChange;
    }

    public void setsTempChange(String sTempChange) {
        this.sTempChange = sTempChange;
    }

    public boolean isTnAvailable() {
        return tnAvailable;
    }

    public void setTnAvailable(boolean tnAvailable) {
        this.tnAvailable = tnAvailable;
    }

}

public static void main(String[] args) {

    ObjectMapper objectMapper = new ObjectMapper();

//  objectMapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true);

    SomeData someData = new SomeData();
    someData.setsTempChange("trial_000");
    someData.setTnAvailable(true);

//  objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
//  objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
//  objectMapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.ANY);
//  objectMapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY);

    try {
        System.out.println("Serialize: " + objectMapper.writeValueAsString(someData));

        String json = "{ \"tnAvailable\": false, \"sTempChange\": \"trial_001\" }";

        SomeData anotherData = objectMapper.readValue(json, SomeData.class);

        System.out.println("Deserialize: " + anotherData.isTnAvailable() + ", " + anotherData.getsTempChange());

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

}

}

我知道我可以强迫它。我更想知道是什么让它困惑。我知道我可以强迫它。更渴望知道是什么使它困惑。可能的重复-那一个有一个虽然=)@Windle问题,尽管那里几乎与相同的情况有关。但我期待着这一切的原因