JFinal—Json2Model

凯撒大弚 发布于 2012/08/27 11:43
阅读 4K+
收藏 3

@JFinal 你好,想跟你请教个问题:

今天用jackson从json转对象的时候发现json2model的时候报错,异常如下:

 

json字符串:{"user":{"email":"hello@hw.com","password":"world"}}
 org.codehaus.jackson.map.JsonMappingException: 
Conflicting setter definitions for property "attrs": 
com.jfinal.plugin.activerecord.Model#setAttrs(1 params)
 vs com.jfinal.plugin.activerecord.Model#setAttrs(1 params)

觉得应该是jfinal对model做了特别的处理,没有了getter、setter之后json工具好像就不能用了,不知道jfinal里面想要从json转model该做那些处理呢?

加载中
2
a
alvinte
1、错误里面所谓的conflict指的是
public Model<M> setAttrs(Map<String, Object> attrs)

public Model<M> setAttrs(M model)
这两个方法。
2、以上说明jackson对class做了预解析(反射+映射),Model里面没有实际的数据属性,所以这种预解析方式并不适合Model
3、即使jackson不做预解析,直接反射setter方法,Model里面默认也没有setter。所以依然是无法转换回去的……
结论就是,AR-Model这种数据结构貌似不适合默认的json2Model方式,需要json工具对这种数据结构的支持,或者看看能不能采取曲线方式:json2Map<String, Object>+Model.setAttrs(Map<String, Object>)
1
凯撒大弚
凯撒大弚

引用来自“alvinte”的答案

1、错误里面所谓的conflict指的是
public Model<M> setAttrs(Map<String, Object> attrs)

public Model<M> setAttrs(M model)
这两个方法。
2、以上说明jackson对class做了预解析(反射+映射),Model里面没有实际的数据属性,所以这种预解析方式并不适合Model
3、即使jackson不做预解析,直接反射setter方法,Model里面默认也没有setter。所以依然是无法转换回去的……
结论就是,AR-Model这种数据结构貌似不适合默认的json2Model方式,需要json工具对这种数据结构的支持,或者看看能不能采取曲线方式:json2Map<String, Object>+Model.setAttrs(Map<String, Object>)

通过@alvinte 提供的思路已经搞定了,非常感谢,现将代码贴出来供大家参考。

本文采用jackson进行json的解析,原因是看了http://wangym.iteye.com/blog/738933这篇对比。

jackson下载地址:http://jackson.codehaus.org/1.7.6/jackson-all-1.7.6.jar

jfinal下载地址,大家都懂的

按照alvinte的思路先是把json【{"user":{"email":"hello@hw.com","password":"world"}}】剥离一层,即去掉外层的user,在类中先test解析了一下:

String json = "{\"user\":{\"email\":\"hello@hw.com\",\"password\":\"world\"}}";
int f = json.lastIndexOf("{");
int e = json.indexOf("}");
System.out.println(json.substring(f, e + 1));

返回结果正如所需:{"emial":"hello@hw.com","password":"world"}

接下来实现json2Map,代码如下:

private static ObjectMapper objectMapper = null;
/**
 * json字符串转Map
 * 
 * @param json
 * @return 
 * @throws Exception
 */
@SuppressWarnings("unchecked")
public static Map<String, Object> json2Map(String json) throws Exception {
	json = URLDecoder.decode(json, "utf-8");
	objectMapper = new ObjectMapper();
	Map<String, Object> maps = objectMapper.readValue(
		json.substring(json.lastIndexOf("{"), json.indexOf("}") + 1),	Map.class);
	return maps;
}

ok,json数据已成功转为Map对象了,最后一步到了jfinal一行代码搞定一切的时候了:

User u = new User();
u.setAttrs(JacksonUtil.json2Map(json));

Over!

 

JFinal
JFinal
回复 @alvinte : 所以,这事最好能有此迫切需求的朋友来做个实现并测试 :)
a
alvinte
回复 @JFinal : 严重同意此顾虑 \(^o^)/
JFinal
JFinal
JFinal 将会给出转换接口,开发者可以自行利用第三方json包来实现更高性能的转换程序。JFinal 可能会提供一个 fast-json 或 gson 实现。但有一点顾虑:或许这些json转换工具对jfinal的 Model 转换效率并不高
JFinal
JFinal
后续的 JFinal 版本,我打算在 Constants加个配置:setJsonBuilder(JsonBuilder.FAST_JSON),将FastJson集成进来,以应对那类大型的 json 数据应用 :)
1
凯撒大弚
凯撒大弚

看了http://www.oschina.net/question/54100_30041这篇文章之后决定还是用fastjson来处理json数据了,阿里的攻城师确实不赖,分享精神值得推崇,今天把jackson的json2Map换成了fastjson2Map了,代码如下,供大家参考:

/**
 * fastjson转Map
 * 
 * @param json
 * @throws UnsupportedEncodingException
 */
@SuppressWarnings("unchecked")
public static Map<String, Object> fastjson2Map(String json)
			throws UnsupportedEncodingException {
	json = URLDecoder.decode(json, "utf-8");
	return (Map<String, Object>) JSON.parse(json.substring(
			json.lastIndexOf("{"), json.indexOf("}") + 1));
}

0
JFinal
JFinal

    @alvinte 的回答说明了问题,关键在于 Model 既无 attribute 也无 setter getter,而jackson 转model 只能是对传统的 bean 做转换。

    如果要实现这个需求,除了使用 @alvinte 的建议先试着转成 Map 再 set到Model 中去以外,再看看 jackson 有无回调接口,可以人工干预一下转换策略,另外如果这类转换很少的话,建议再单建个带有setter getter attribute 的Bean继承自现有Model :)

凯撒大弚
凯撒大弚
@JFinal 嗯嗯、支持是必须的
JFinal
JFinal
回复 @雅各布奇 : 哈哈,这叫前瞻性设计,多提建议哈 :)
凯撒大弚
凯撒大弚
回复 @JFinal : getter、setter的话可能会麻烦点儿,如果后续还有多个属性的就需要配置多个,而先转换成Map的话就避免了这个问题的出现,jfiinal中model的setAttrs(Map<String,Object> map)方法像是为这种情况准备似的,Niice!哈哈
JFinal
JFinal
回复 @alvinte : 我觉得先转成 Map 或许是最好的办法,看楼主回应了 :)
a
alvinte
有回调其实就最好了,不过估计够呛……
下一页
返回顶部
顶部