使用 Jackson 将通用 java 对象序列化为 JSON

Posted

技术标签:

【中文标题】使用 Jackson 将通用 java 对象序列化为 JSON【英文标题】:Serializing generic java object to JSON using Jackson 【发布时间】:2011-12-23 17:37:50 【问题描述】:

当我尝试将以下类实例转换为 JSON(使用 Jackson)时

public class RPCRespond<Result> 

    private int code;
    private Result result;
    private boolean success;
    private String failureReason;

    public RPCRespond() 
        this.code = 0;
        this.success = true;
        this.result = null;
    

    public RPCRespond(Result result) 
        this.code = 0;
        this.success = true;
        this.result = result;
    

    public RPCRespond(int code, String failureReason) 
        this.code = code;
        this.success = false;
        this.failureReason = failureReason;
    

    public RPCRespond(int code, String failureReason, Object... args) 
        this.code = code;
        this.success = false;
        this.failureReason = String.format(failureReason, args);
    

    public Result getResult() 
        return result;
    


    public void setSuccess(boolean success) 
        this.success = success;
    

    public String getFailureReason() 
        return failureReason;
    

    public void setFailureReason(String failureReason) 
        this.failureReason = failureReason;
    

    public int getCode() 
        return code;
    

    public boolean getSuccess() 
        return success;
    

    @Transient
    public String getAsJSON() 

        String json = "";

        ObjectMapper mapper = new ObjectMapper();
        json = mapper.writeValueAsString(this) ; 

        return json ;
    


进入无限循环:

在 sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:601) 在 org.codehaus.jackson.map.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:483) 在 org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:418) 在 org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) 在 org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) 在 org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610) 在 org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256) 在 org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2566) 在 org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2088)

RPCRespond 的发起是由

User u = new User() ;
u.setFirstName("aaaa") ;
RPCRespond<User> result = new RPCRespond<User>(u) ;

result.setSuccess(true) ;

return result.getAsJSON() ;

如何将 RPCRespond 转换为 JSON?

【问题讨论】:

完全不相关,但是 ctor 签名让我有点冷——我宁愿看到明确命名成功/失败状态的小工厂,而不是具有怪异语义的 ctor。也不确定为什么将字符串设置为空白,然后立即用 JSON 覆盖它。 为了简单起见,我删除了一些代码 您是否尝试过使用@JsonIgnore 注释?我不知道它是否会默认跳过 @Transient 属性。这是一个 Hibernate 实体吗? 用户是 pojo 对象,还没有休眠注释。我确实计划稍后添加它们。你建议在哪里添加@jsonignore? 致可能导致无限循环的吸气剂。 【参考方案1】:

正如其他人所建议的,这很可能是由于循环引用;默认情况下,Jackson 不处理此类依赖项。

您可以尝试跳过该属性的序列化,或者,如果它是父/子类型链接,则对其进行注释(有关详细信息,请参阅 Jackson Wiki 上的“bi-directional references”条目)。

不管怎样,泛型类型不会导致这种情况(也就是说,这可能只是一个巧合);循环类型非常好。

【讨论】:

您是我的英雄。节省了 0.5 PD。【参考方案2】:

默认情况下,Jackson 将通过get 方法进行序列化。一旦遇到getAsJson 方法,poom,无限循环。用@JsonIgnore 注释标记它。

@JsonIgnore
public String getAsJSON() 
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(this) ; 

您还可以将 Jackson 配置为仅基于属性进行序列化,这可能会消除对 @JsonIgnore 的需求,但这可能会也可能不会满足您的需求。

相信最新的 Jackson 允许选择使用 Hibernate @Transient 注释,尽管我不确定如何配置它(最近的变化)。

【讨论】:

(对downvoting 的解释/说明通常受到赞赏。) @JsonIgnore 拯救了我的一天

以上是关于使用 Jackson 将通用 java 对象序列化为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Jackson ObjectMapper 将 Json 序列化为 Java 对象

如何使用 Jackson 将原始 JSON 反序列化为 Java 对象

jackson中objectMapper的使用

使用Jackson将JSON数组反序列化为单个Java对象

使用 Jackson 将文件类型从 Angular 反序列化为 Java

如何使用jackson(Java)反序列化对象中的json对象?