关于sojo输出json中出现~unique-id~字样的问题

问题:在项目中,问题的表现如下,使用SojoJsonStringWriter,当需要序列化一个对象成json格式时
class Result {
  List<Broadcast> broadcasts;
  ...
}
class Broadcast {
  List<Presenter> presenters;
  ...
}

如果result中的多个broadcast共用了同一个presenter,输出结果中,第一个broadcast中的presenter正常,而第2、3个presenter显示为~unique-id~1。
原因:
Spring集成jsonview的时候,其中有以下两种方式较为常用,
SojoJsonStringWriter:必须要有set/get方法,对boolean;is不会序列化,只能用get替代;对共用对象的多次解析会出现~unique-id~(可能是因为Hibernate持久中的延迟加载的缘故)
JsonlibJsonStringWriter:功能上没有前者强,如类型需要自己转化,但可以通过定制JsonConfig来实现;不会出现对共用对象的多次解析会出现~unique-id~
解决方案:
使用JsonlibJsonStringWriter,在views.xml中新增
<bean name="jsonlibView" class="org.springframework.web.servlet.view.json.JsonView">
  <property name="encoding" value="UTF-8" />
  <property name="contentType" value="application/json" />
  <property name="jsonWriter" ref="jsonlibJsonStringWriter" />
  <property name="jsonErrors">
    <list>
      <ref bean="statusError" />
      <ref bean="modelflagError" />
    </list>
  </property>
</bean>
<bean name="jsonlibJsonStringWriter" class="org.springframework.web.servlet.view.json.writer.jsonlib.JsonlibJsonStringWriter">
  <property name="convertAllMapValues" value="true" />
  <property name="enableJsonConfigSupport" value="true" />
</bean>


此时,直接使用,可能会出现异常:net.sf.json.JSONException: java.lang.NoSuchMethodException: Property 'delegate' has no getter method
这是因为实体对象用的是Hibernate的延迟加载,可以通过以下方式解决:
public class HibernateJsonBeanProcessor implements JsonBeanProcessor {
  public JSONObject processBean(Object obj, JsonConfig jsonConfig) {
    return new JSONObject();
  }
}
public class HibernateJsonBeanProcessorMatcher extends JsonBeanProcessorMatcher {
  private final Log logger = LogFactory.getLog(HibernateJsonBeanProcessorMatcher.class);
  @SuppressWarnings("unchecked")
  @Override
  public Object getMatch(Class target, Set set) {
    if (target.getName().contains("$$EnhancerByCGLIB$$")) {
      logger.warn("Found Lazy-References in Hibernate object " + target.getName());
      return org.hibernate.proxy.HibernateProxy.class;
    }
    return DEFAULT.getMatch(target, set);
  }
}
public class HibernateJsonlibJsonWriterConfiguratorTemplate extends JsonlibJsonWriterConfiguratorTemplate {
  @Override
  public JsonConfig getJsonConfig() {
    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.registerJsonBeanProcessor(HibernateProxy.class, new HibernateJsonBeanProcessor());
    jsonConfig.setJsonBeanProcessorMatcher(new HibernateJsonBeanProcessorMatcher());
    return jsonConfig;
  }
}

在controller的方法返回mav之前,执行以下代码进行注册config
JsonWriterConfiguratorTemplateRegistry registry = JsonWriterConfiguratorTemplateRegistry.load(request);
registry.registerConfiguratorTemplate(new HibernateJsonlibJsonWriterConfiguratorTemplate());


此时调试,可能会出现另一个异常:net.sf.json.JSONException: There is a cycle in the hierarchy
这可能是Bean对象里有循环调用的属性,解决办法是,增加循环应对的策略,
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
或者设置过滤字段,将有可能循环的属性过滤掉,config.setExcludes(new String[])
这里还可以增加别的功能,如
config.setIgnoreDefaultExcludes(false);
config.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor("MM/dd/yyyy"));
...

至此,问题解决。
参考:
http://spring-json.sourceforge.net/binding.html
http://www.cnblogs.com/yueue/archive/2010/02/23/1672059.html
http://pipe.iteye.com/blog/224564

你可能感兴趣的:(spring,.net,bean,json,Hibernate)