这可能是重复的。但我无法找到解决问题的方法。
我有一个班级
public class MyResponse implements Serializable {
private boolean isSuccess;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Getter和setter由Eclipse生成。
在另一个类中,我将值设置为true,并将其写为JSON字符串。
System.out.println(new ObjectMapper().writeValueAsString(myResponse));
在JSON中,密钥以{"success": true}
开头。
我希望密钥为isSuccess
本身。 Jackson是否在序列化时使用setter方法?如何使密钥成为字段名称本身?
答案 0 :(得分:68)
这是一个稍晚的答案,但对于访问此页面的其他人可能会有用。
更改Jackson在序列化为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;
}
}
然后将其序列化为JSON {"isSuccess":true}
,但其优点是无需修改getter方法名称。
请注意,在这种情况下,您还可以将注释编写为@JsonProperty("isSuccess")
,因为它只有单个value
元素
答案 1 :(得分:17)
我最近碰到了这个问题,这就是我发现的。杰克逊将检查你传递给它的任何课程的getter和setter,并使用这些方法进行序列化和反序列化。这些方法中的“get”,“is”和“set”后面的内容将用作JSON字段的键(getIsValid和setIsValid的“isValid”)。
public class JacksonExample {
private boolean isValid = false;
public boolean getIsValid() {
return isValid;
}
public void setIsValid(boolean isValid) {
this.isValid = isValid;
}
}
同样“isSuccess”将成为“成功”,除非重命名为“isIsSuccess”或“getIsSuccess”
在此处阅读更多内容:http://www.citrine.io/blog/2015/5/20/jackson-json-processor
答案 2 :(得分:2)
以Utkarsh的答案为基础......
Getter名称减去 get / is 用作JSON名称。
public class Example{
private String radcliffe;
public getHarryPotter(){
return radcliffe;
}
}
存储为 {" harryPotter" :"无论你怎么样?" }
对于反序列化,Jackson会同时检查setter和字段名称。 对于Json String {" word1" :"示例" } ,以下两者都有效。
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 ;
}
}
一个更有趣的问题是杰克逊考虑反序列化的顺序。如果我尝试反序列化 {" word1" :" myName" 与
public class Example3{
private String word1;
private String word2;
public setWord1( String parameter){
this.word2 = parameter ;
}
}
我没有测试上面的情况,但看到 word1 &的价值会很有趣。 word2 ...
注意:我使用了截然不同的名称来强调哪些字段必须相同。
答案 3 :(得分:2)
您可以如下配置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);
}
});
答案 4 :(得分:1)
还有另一种解决此问题的方法。
只需定义一个新的子类扩展PropertyNamingStrategy并将其传递给ObjectMapper实例。
这里的代码段可能会有所帮助:
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;
}
});
答案 5 :(得分:1)
使用Kotlin和数据类时:
data class Dto(
@get:JsonProperty("isSuccess") val isSuccess: Boolean
)
如果还要反序列化JSON,则可能需要添加@param:JsonProperty("isSuccess")
。
答案 6 :(得分:0)
您应该将配置添加到Jakson对象映射器,例如:
var mostUsedCompanyId = _context ...
答案 7 :(得分:0)
我不想弄乱某些自定义命名策略,也不想重新创建一些访问器。
代码越少,我越快乐。
这对我们有用:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.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;
}
答案 8 :(得分:0)
接受的答案不适用于我的情况。
就我而言,该课程不是我所有的。有问题的类来自第三方的依赖关系,因此我不能只在其中添加@JsonProperty
注释。
要解决此问题,受上述@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);
}
});
基本上,这是在序列化和反序列化之前,它检查目标/源类中该类中存在哪些属性名称,无论是isEnabled
还是enabled
属性。
基于此,映射器将序列化和反序列化为存在的属性名称。
答案 9 :(得分:0)
您可以将原始布尔值更改为java.lang.Boolean(+使用@JsonPropery
)
@JsonProperty("isA")
private Boolean isA = false;
public Boolean getA() {
return this.isA;
}
public void setA(Boolean a) {
this.isA = a;
}
对我来说很棒。
答案 10 :(得分:0)
如果您有兴趣处理不受您控制的 3rd 方类(如评论中提到的 @edmundpie),那么您将 Mixin 类添加到您的 ObjectMapper 中,其中属性/字段名称应与您的 3rd 方类中的名称相匹配:< /p>
public class MyStack32270422 {
public static void main(String[] args) {
ObjectMapper om3rdParty = new ObjectMapper();
om3rdParty .addMixIn(My3rdPartyResponse.class, MixinMyResponse.class);
// add further mixins if required
String jsonString = om3rdParty.writeValueAsString(new My3rdPartyResponse());
System.out.println(jsonString);
}
}
class MixinMyResponse {
// add all jackson annotations here you want to be used when handling My3rdPartyResponse classes
@JsonProperty("isSuccess")
private boolean isSuccess;
}
class My3rdPartyResponse{
private boolean isSuccess = true;
// getter and setter here if desired
}
基本上,您将所有 Jackson 注释添加到 Mixin 类中,就好像您拥有该类一样。在我看来,这是一个很好的解决方案,因为您不必检查以“is..”开头的方法名称等等。