如何在Java中将字符串附加到JSON字符串?

4
我正在这样获取来自Zookeeper节点的数据:
byte[] bytes = client.getData().forPath("/my/example/node1");
String ss = new String(bytes);

这里ss将会有像这样的数据,它是一个简单的JSON字符串,包含键值对 -

{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0"}

现在我想在上述JSON字符串末尾添加一个键值对。这是我想要添加的键值对 -
"version":"v3"

因此,最终的JSON字符串将如下所示 -
{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0", "version":"v3"}

什么是最好且高效的方法来实现这个?

1
一般情况下,不要这样做。你可以在有限的情况下通过进行明显的字符串操作来实现,但是在一般情况下,更好的方法是反序列化JSON,修改生成的Map,然后重新序列化Map。 - Hot Licks
1
你需要一个JSON解析器。 - SLaks
@HotLicks,除非你能给出真正的理由,否则我不会接受那个论点。特别是如果他只是在学习。不要过度设计问题。 - SpacePrez
1
请务必在使用接受字节数组参数的String构造函数时指定字符集,不要忘记。否则,如果平台的默认编码与您期望的不一致,您的代码可能会出错。对于JSON数据,您应该使用UTF-8字符集,所以可以这样写:new String(bytes, StandardCharsets.UTF_8)。 - dnault
@PNS 如果你能给出一点点理由就太好了。但是,让我们继续重复相同的答案吧! - SpacePrez
显示剩余4条评论
3个回答

10
使用JSON解析器/生成器将给定的JSON解析为树形结构,然后添加JSON字段。使用Gson,代码大致如下:
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(ss, JsonObject.class); // parse
jsonObject.addProperty("version", "v3"); // modify
System.out.println(jsonObject); // generate

打印

{"description":"Some Text","machinename":"machineA","ipaddress":"192.128.0.0","version":"v3"}

Zookeeper返回的是有效的JSON格式还是他们自己的定制格式?要注意这一点。


谢谢。是的,Zookeeper总是返回有效的JSON,因为我只在节点内存储数据时使用了这种格式(JSON文档)。因此,当我检索它时,它会将之前编写的相同JSON字符串返回给我。 - user2467545
1
Jackson JSON 库被广泛使用。 - Daniel Nuriyev
如果他想要最有效的方式,这就过度了。 - SpacePrez
@DanielNuriyev 当然,Jackson的ObjectMapper有一个相应的方法可以为您提供一个ObjectNode - Sotirios Delimanolis
1
@Zaphod42 效率不仅适用于代码执行的速度,还与编写代码、维护代码等方面有关。 - Sotirios Delimanolis
@SotiriosDelimanolis 是的,但是你的方法会从完整字符串创建一个对象,然后再进行反序列化;如果你可以简单地添加一个字符串,那么这种方法就是浪费的。基本的Java字符串操作没有任何不可维护的部分。你可以将此方法放在静态类中。 - SpacePrez

2
当涉及到JSON处理时,仅在特殊且简单的情况下才能使用字符串操作。对于一般情况,应使用优秀的JSON解析库。Jackson在性能、效率、多功能和可靠性方面处于前列,并且是根据商业友好的Apache 2.0许可发布的。以下是在Jackson中请求答案的简单实现。
public static void main(String[] args)
{
    String ss = "{\"description\":\"Some Text\", \"machinename\":\"machineA\", \"ipaddress\":\"192.128.0.0\"}";

    System.out.println("JSON string before: " + ss);

    try
    {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String> map = (Map<String, String>)mapper.readValue(ss, Map.class);
        
        map.put("version", "v3");
        ss = mapper.writeValueAsString(map);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    System.out.println("JSON string after: " + ss);
}

可能更容易使用ObjectMapper方法,该方法会给您一个JsonNode,将其强制转换为ObjectNode并进行修改。 - Sotirios Delimanolis
没错,我只是选择了简单的解释方式。在实际的代码中,我更喜欢使用JsonNode。谢谢。 - PNS

1
基本的字符串操作。在最后的闭合括号 } 前插入你的额外字符串。请确保加上逗号。
Json对象不需要排序。
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"}";

String json2 = "\"version\":\"v3\"";

json2 = ',' + json2;

String json3 = json.substring(0,json.length()-1) + json2 + json.charAt(json.length()-1);

如果这是你所需要做的全部内容,那么这应该是最简单、最有效的方法。

如果想要了解更多有关字符串操作的内容,请参考以下阅读资料:

http://docs.oracle.com/javase/tutorial/java/data/manipstrings.html


尝试编译它。错误很小,但我希望你能修复它。 - Sotirios Delimanolis
好的,完成了。如果你想帮忙,你应该指出问题所在。虽然问题非常小,但我忘记了在Java中长度是一个方法而不是公共字段,对不起。 - SpacePrez
1
我希望这个练习展示了自己逐个生成JSON的低效率。 - Sotirios Delimanolis
3
使用字符串处理来生成(甚至更糟的是,编辑)JSON字符串通常是一个非常糟糕的主意。对于简单情况而言,它可能有效,但这并不代表它是良好的编程风格。我已经为你的答案点赞,因为我认为负面评价是不尊重的(至少当回答还算不错时),但Sotirios所说的是正确的,没有必要紧张。 :-) - PNS
1
当然可以,但是你知道编程不是只考虑特殊情况,而且通常不应该通过字符串处理来进行JSON处理。即使对JSON字符串进行最微小的修改也可能会破坏它,尤其是如果这些修改来自用户输入,其中可能包含需要转义的特殊字符。因此,JSON操作应始终通过JSON解析器进行。 - PNS
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接