hi,问题是这样的,假设有一个java对象A,A里面有个String类型的字段data,data里面存放的是一个json串,现在我要将json串形式的A转化成一个java对象,这个过程中希望这个data字段还是以一个String的形式存在(即过程中不对data字段进行json到java的转换),有办法吗?
p.s. 如果问题描述不清,还请指出。
JSONObject
或者GSON,google实现的JSON形式
如有必要在贴上示例代码。
先理解一下 lz 的意思:
String str = "{ \"data\": \"{a:1,b:2}\" }";
JSONObject json = (JSONObject)JSONSerializer.toJSON(str);
System.out.println(json.getString("data"));
data 是一个 string ,其内容正好是一个 json 。输出为:
{"a":1,"b":2}
但期望的输出是
{a:1,b:2}
也就是说,toJSON 这个方法会自动把那些“可能是json”的字符串转换成 json object 。楼主希望 disable 掉这个 feature 。
如果我上面的理解没错的话。简单地说就是不可能。下面写一下分析过程:
我一开始认为这个库应该有一些 config 可以设置,查了一下 API 发现了 JsonConfig 这个类,但里面貌似没有相关的配置。于是我下了 json-lib 的源代码来看。
先从 JSONSerializer.toJSON() 看起,最后我发现 JSONObject.element(String key, Object value, JsonConfig jsonConfig) 这个方法就是有问题的。
证实一下这个结论,下面的代码,也会输出 {"a":1,"b":2}
:
json = new JSONObject();
json.element("data", "{a:1,b:2}");
System.out.println(json.getString("data"));
调用链:
JSONObject.element()
-> JSONObject.processValue()
-> JSONObject._processValue()
-> AbstractJSON._processValue()
最终定位到 AbstractJSON._processValue(Object value, JsonConfig jsonConfig) 这个方法
在这个方法里有一个 if( JSONUtils.isString( value ) ) 分支,它里面有一个 if( JSONUtils.mayBeJSON( str ) ) 分支。
看到这里代码的意图就明白了,mayBeJSON 会测试串是否“像”json,然后会递归调用 toJSON()
但似乎没有什么在 JsonConfig 我们能够控制的东西能够改变这个过程。
最后我找到了一个 word-around:将你的 json 改成:
{ "data": "'{a:1,b:2}'" }
也就是在双引号里面多加一层引号,会出来 {a:1,b:1}
。
但这里又有问题了,为什么 json-lib 会自己删除里面那层引号呢?上面的例子期望的结果应该是 '{a:1,b:1}'
才对吧?
所以 lz 应该可以看出 json-lib 的处理方式有很大问题。这里推荐 lz 使用 google 的 gson ,代码如下:
import org.junit.Assert;
import com.google.gson.Gson;
public class JsonTest {
static class A {
String data;
}
public static void main(String[] args) {
final Gson gson = new Gson();
final A a = gson.fromJson("{ \"data\": \"{a:1,b:2}\" }", A.class);
Assert.assertEquals("{a:1,b:2}", a.data);
}
}
通过反射,做到了类型安全的 json 解析,而且代码也很优雅。
P.S. lz 的问题描述确实是有些模糊的,清晰的问题描述参考我这个答案的开头部分。问题主要在于,作为一个没用过 json-lib 的人来看,会想,“data 既然是 String ,那么转成 java 之后肯定也是 String 罗”,谁会想到 json-lib 会自动把 string 变成 object 。