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

Ben*_*rns 7 java serialization json json-lib

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

例如:

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"));
Run Code Online (Sandbox Code Playgroud)

打印:

{"jsonStringValue":{"hello":"world"},"naturalStringValue":"\"hello world\""}
{"hello":"world"}
"hello world"
Run Code Online (Sandbox Code Playgroud)

我希望它打印:

{"jsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}
{"hello":"world"}
"hello world"
Run Code Online (Sandbox Code Playgroud)

是的,我意识到这是令人讨厌的.但是,这支持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"));
Run Code Online (Sandbox Code Playgroud)

输出:

{"naturalJSONValue":{"hello":"world"},"escapedJSONValue":"{\\\"hello\\\":\\\"world\\\"}"}
{"hello":"world"}
{\"hello\":\"world\"}
Run Code Online (Sandbox Code Playgroud)

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

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

mar*_*ear 5

这对我来说对json-lib 2.4有用:

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

输出是:

{"jsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}
Run Code Online (Sandbox Code Playgroud)

这是一个可能的解决方案吗?

更新:

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


Pau*_*l V 1

使用单引号来引用字符串。从文档中:

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

如果字符串不以引号或单引号开头,并且不包含前导或尾随空格,并且不包含以下任何字符: { } [ ] / \ ,则根本不需要用引号引起来: , = ; # 如果它们看起来不像数字并且它们不是保留字 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"));
Run Code Online (Sandbox Code Playgroud)

生产:

{"jsonStringValue":{"hello":"world"},"quotedJsonStringValue":"{\"hello\":\"world\"}","naturalStringValue":"\"hello world\""}
{"hello":"world"}
{"hello":"world"}
"hello world"
Run Code Online (Sandbox Code Playgroud)

请注意如何quotedJsonStringValue将其视为字符串值而不是 JSON,并在输出 JSON 中出现引用。

  • @marsbear,如果数据可以包含单引号,那么是的,它们需要被转义或删除。使用 `object().key().value()` 肯定会更容易,我只是插话,因为 @Ben 似乎需要一个仅使用 `JSONObject` 的解决方法。 (2认同)