如何强制JSON-lib的JSONObject.put(..)转义包含JSON的字符串?

时间:2011-05-27 17:10:59

标签: java json serialization json-lib

使用JSON-lib的JSONObject时,如何阻止put方法存储包含JSON而不是转义字符串的字符串?

例如:

JSONObject obj = new JSONObject();
obj.put("jsonStringValue","{\"hello\":\"world\"}");
obj.put("naturalStringValue", "\"hello world\"");
System.out.println(obj.toString());
System.out.println(obj.getString("jsonStringValue"));
System.out.println(obj.getString("naturalStringValue"));

打印:

{"jsonStringValue":{"hello":"world"},"naturalStringValue":"\"hello world\""}
{"hello":"world"}
"hello world"

我希望它打印出来:

{"jsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}
{"hello":"world"}
"hello world"

是的,我意识到这是令人讨厌的。但是,这支持JSON序列化管道,为了互操作性,这是预期的行为。在某些情况下,我们会序列化可能包含有效JSON的用户输入。我们不希望用户输入成为我们将所述输入序列化的JSON对象的一部分。

手动转义不起作用,因为它导致JSON-lib转义\个字符:

JSONObject obj = new JSONObject();
obj.put("naturalJSONValue","{\"hello\":\"world\"}");
obj.put("escapedJSONValue", "{\\\"hello\\\":\\\"world\\\"}");
System.out.println(obj.toString());
System.out.println(obj.getString("naturalJSONValue"));
System.out.println(obj.getString("escapedJSONValue"));

输出:

{"naturalJSONValue":{"hello":"world"},"escapedJSONValue":"{\\\"hello\\\":\\\"world\\\"}"}
{"hello":"world"}
{\"hello\":\"world\"}

此时,任何启用手动选择性转义复杂JSON对象的变通方法都会完全否定首先使用JSON-lib的价值。

另外,我知道这个问题已经被问到before,但不幸的是我不能轻易接受它的回答。 JSON-lib在我的项目的许多方面都是一个经常使用的依赖项,并且交换它将是一项艰巨的任务。我需要绝对确定在我可以接受与Jackson,simple-json或Gson的交换之前,没有办法用JSON-lib实现这个目标。

2 个答案:

答案 0 :(得分:5)

这适用于json-lib 2.4:

System.out.println(
    new JSONStringer()
        .object()
            .key("jsonStringValue")
                .value("{\"hello\":\"world\"}")
            .key("naturalStringValue")
                .value("\"hello world\"")
        .endObject()
    .toString());

输出结果为:

{"jsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}

这可能是您的解决方案吗?

<强>更新

使用可能的解决方案修改我的答案

答案 1 :(得分:2)

使用单引号引用字符串。来自documentation

  

字符串可以用'(单引号)引用。

     

如果字符串不以引号或单引号开头,并且如果它们不包含前导或尾随空格,并且它们不包含任何这些字符,则根本不需要引用它们:{} [] / \:,=; #并且如果它们看起来不像数字,并且它们不是保留字true,false或null。

所以修改你的例子:

net.sf.json.JSONObject obj = new net.sf.json.JSONObject();
obj.put("jsonStringValue","{\"hello\":\"world\"}");
obj.put("quotedJsonStringValue","\'{\"hello\":\"world\"}\'");
obj.put("naturalStringValue", "\"hello world\"");
System.out.println(obj.toString());
System.out.println(obj.getString("jsonStringValue"));
System.out.println(obj.getString("quotedJsonStringValue"));
System.out.println(obj.getString("naturalStringValue"));

产地:

{"jsonStringValue":{"hello":"world"},"quotedJsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}
{"hello":"world"}
{"hello":"world"}
"hello world"

注意quotedJsonStringValue如何被视为字符串值而非JSON,并在输出JSON中显示。