Java Jackson 通过删除“is”来重命名原始布尔字段

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

Hymanson renames primitive boolean field by removing 'is'

javajsonHymanson

提问by iCode

This might be a duplicate. But I cannot find a solution to my Problem.

这可能是重复的。但是我找不到解决我的问题的方法。

I have a class

我有一堂课

public class MyResponse implements Serializable {

    private boolean isSuccess;

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

Getters and setters are generated by Eclipse.

Getter 和 setter 由 Eclipse 生成。

In another class, I set the value to true, and write it as a JSON string.

在另一个类中,我将该值设置为 true,并将其写为 JSON 字符串。

System.out.println(new ObjectMapper().writeValueAsString(myResponse));

In JSON, the key is coming as {"success": true}.

在 JSON 中,关键是作为{"success": true}.

I want the key as isSuccessitself. Is Hymanson using the setter method while serialization? How to make the key the field name itself?

我想要钥匙isSuccess本身。Hymanson 在序列化时是否使用 setter 方法?如何使键成为字段名称本身?

采纳答案by Scott

This is a slightly late answer, but may be useful for anyone else coming to this page.

这是一个稍晚的答案,但可能对访问此页面的其他人有用。

A simple solution to changing the name that Hymanson will use for when serializing to JSON is to use the @JsonPropertyannotation, so your example would become:

更改 Hymanson 在序列化为 JSON 时将使用的名称的一个简单解决方案是使用@JsonProperty注释,因此您的示例将变为:

public class MyResponse implements Serializable {

    private boolean isSuccess;

    @JsonProperty(value="isSuccess")        
    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

This would then be serialised to JSON as {"isSuccess":true}, but has the advantage of not having to modify your getter method name.

然后将其序列化为 JSON as {"isSuccess":true},但具有不必修改 getter 方法名称的优点。

Note that in this case you could also write the annotation as @JsonProperty("isSuccess")as it only has the single valueelement

请注意,在这种情况下,您也可以编写注释,@JsonProperty("isSuccess")因为它只有单个value元素

回答by Utkarsha Padhye

I recently ran into this issue and this is what I found. Hymanson will inspect any class that you pass to it for getters and setters, and use those methods for serialization and deserialization. What follows "get", "is" and "set" in those methods will be used as the key for the JSON field ("isValid" for getIsValid and setIsValid).

我最近遇到了这个问题,这就是我发现的。Hymanson 将检查您传递给它的任何类的 getter 和 setter,并使用这些方法进行序列化和反序列化。这些方法中“get”、“is”和“set”之后的内容将用作 JSON 字段的键(getIsValid 和 setIsValid 的“isValid”)。

public class HymansonExample {   

    private boolean isValid = false;

    public boolean getIsValid() {
        return isValid;
    }

    public void setIsValid(boolean isValid) {
        this.isValid = isValid;
    }
} 

Similarly "isSuccess" will become "success", unless renamed to "isIsSuccess" or "getIsSuccess"

同样,“isSuccess”将变成“success”,除非重命名为“isIsSuccess”或“getIsSuccess”

Read more here: http://www.citrine.io/blog/2015/5/20/Hymanson-json-processor

在此处阅读更多信息:http: //www.citrine.io/blog/2015/5/20/Hymanson-json-processor

回答by Abhinav Vishak

Building upon Utkarsh's answer..

以 Utkarsh 的回答为基础..

Getter names minus get/isis used as the JSON name.

Getter 名称减去get/is用作 JSON 名称。

public class Example{
    private String radcliffe; 

    public getHarryPotter(){
        return radcliffe; 
    }
}

is stored as { "harryPotter" : "whateverYouGaveHere" }

存储为{ "harryPotter" : "whateverYouGaveHere" }



For Deserialization, Hymanson checks against both the setter and the field name. For the Json String { "word1" : "example" }, both the below are valid.

对于反序列化,Hymanson 会同时检查 setter 和字段名称。对于 Json String { "word1" : "example" },以下两个都是有效的。

public class Example{
    private String word1; 

    public setword2( String pqr){
        this.word1 = pqr; 
    }
}

public class Example2{
    private String word2; 

    public setWord1(String pqr){
        this.word2 = pqr ; 
    }
}


A more interesting question is which order Hymanson considers for deserialization. If i try to deserialize { "word1" : "myName" }with

一个更有趣的问题是 Hymanson 考虑反序列化的顺序。如果我尝试反序列化{“字1”:“MYNAME”}

public class Example3{
    private String word1;
    private String word2; 

    public setWord1( String parameter){
        this.word2 = parameter ; 
    }
}

I did not test the above case, but it would be interesting to see the values of word1& word2...

我没有测试上述案例,但看到word1word2的值会很有趣......

Note: I used drastically different names to emphasize which fields are required to be same.

注意:我使用了截然不同的名称来强调哪些字段需要相同。

回答by eric

there is another method for this problem.

这个问题还有另一种方法。

just define a new sub-class extends PropertyNamingStrategy and pass it to ObjectMapper instance.

只需定义一个新的子类 extends PropertyNamingStrategy 并将其传递给 ObjectMapper 实例。

here is a code snippet may be help more:

这是一个代码片段可能会有更多帮助:

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
        @Override
        public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
            String input = defaultName;
            if(method.getName().startsWith("is")){
                input = method.getName();
            }

            //copy from LowerCaseWithUnderscoresStrategy
            if (input == null) return input; // garbage in, garbage out
            int length = input.length();
            StringBuilder result = new StringBuilder(length * 2);
            int resultLength = 0;
            boolean wasPrevTranslated = false;
            for (int i = 0; i < length; i++)
            {
                char c = input.charAt(i);
                if (i > 0 || c != '_') // skip first starting underscore
                {
                    if (Character.isUpperCase(c))
                    {
                        if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_')
                        {
                            result.append('_');
                            resultLength++;
                        }
                        c = Character.toLowerCase(c);
                        wasPrevTranslated = true;
                    }
                    else
                    {
                        wasPrevTranslated = false;
                    }
                    result.append(c);
                    resultLength++;
                }
            }
            return resultLength > 0 ? result.toString() : input;
        }
    });

回答by borino

You should add configuration to the Jakson object mapper for example:

您应该向 Jakson 对象映射器添加配置,例如:

MappingHymanson2HttpMessageConverter converter = new MappingHymanson2HttpMessageConverter();
converter.getObjectMapper().disable(MapperFeature.AUTO_DETECT_IS_GETTERS);

回答by burak emre

You can configure your ObjectMapperas follows:

您可以ObjectMapper按如下方式配置:

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
            @Override
            public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
            {
                if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
                        && method.getName().startsWith("is")) {
                    return method.getName();
                }
                return super.nameForGetterMethod(config, method, defaultName);
            }
        });

回答by Fabio

Using both annotations below, forces the output JSON to include is_xxx:

使用下面的两个注释,强制输出 JSON 包括is_xxx

@get:JsonProperty("is_something")
@param:JsonProperty("is_something")

回答by Adrien

I didn't want to mess with some custom naming strategies, nor re-creating some accessors.
The less code, the happier I am.

我不想弄乱一些自定义命名策略,也不想重新创建一些访问器。
代码越少,我越开心。

This did the trick for us :

这对我们有用:

import com.fasterxml.Hymanson.annotation.JsonIgnoreProperties;
import com.fasterxml.Hymanson.annotation.JsonProperty;

@JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates 
public class MyResponse {

    private String id;
    private @JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name
    private @JsonProperty("isDeleted") boolean isDeleted;

}

回答by edmundpie

The accepted answer won't work for my case.

接受的答案不适用于我的情况。

In my case, the class is not owned by me. The problematic class comes from 3rd party dependencies, so I can't just add @JsonPropertyannotation in it.

就我而言,该课程不归我所有。有问题的类来自 3rd 方依赖项,所以我不能只@JsonProperty在其中添加注释。

To solve it, inspired by @burak answer above, I created a custom PropertyNamingStrategyas follow:

为了解决这个问题,受上面@burak答案的启发,我创建了一个自定义PropertyNamingStrategy如下:

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
  @Override
  public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
  {
    if (method.getParameterCount() == 1 &&
            (method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) &&
            method.getName().startsWith("set")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = "is" + method.getName().substring(3);

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }

    return super.nameForSetterMethod(config, method, defaultName);
  }

  @Override
  public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
  {
    if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
        && method.getName().startsWith("is")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = method.getName();

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }
    return super.nameForGetterMethod(config, method, defaultName);
  }
});

Basically what this does is, before serializing and deserializing, it checks in the target/source class which property name is present in the class, whether it is isEnabledor enabledproperty.

基本上它所做的是,在序列化和反序列化之前,它会检查目标/源类中存在的属性名称,无论是它isEnabled还是enabled属性。

Based on that, the mapper will serialize and deserialize to the property name that is exist.

基于此,映射器将序列化和反序列化为存在的属性名称。

回答by Eirik Fosse

When you are using Kotlin and data classes:

当您使用 Kotlin 和数据类时:

data class Dto(
    @get:JsonProperty("isSuccess") val isSuccess: Boolean
)

You might need to add @param:JsonProperty("isSuccess")if you are going to deserialize JSON as well.

@param:JsonProperty("isSuccess")如果您还打算反序列化 JSON,则可能需要添加。