首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >javax.json奇怪行为

javax.json奇怪行为
EN

Stack Overflow用户
提问于 2016-02-03 20:32:24
回答 3查看 1.5K关注 0票数 5

我不明白为什么这段代码的最后一行返回一个空字符串。

代码语言:javascript
复制
Map<String, JsonObjectBuilder> HASH_MAP = new HashMap<>();

JsonObjectBuilder one = Json.createObjectBuilder();
one.add("test1","test1");
HASH_MAP.put("one", one);

JsonObjectBuilder two = Json.createObjectBuilder();
two.add("test2","test2");
HASH_MAP.put("two", two);

JsonObjectBuilder toReturn = Json.createObjectBuilder();
JsonArrayBuilder l1 = Json.createArrayBuilder();
for (Map.Entry<String, JsonObjectBuilder> l : HASH_MAP.entrySet()) {
    l1.add(l.getValue());
}

toReturn.add("l1", l1);
toReturn.add("otherParam", "value2");
String strJSON = toReturn.build().toString();
System.out.println("JSON1: " + strJSON);
System.out.println("JSON2: " + HASH_MAP.get("one").build().toString());

这是输出:

代码语言:javascript
复制
Info:   JSON1: {"l1":[{"test1":"test1"},{"test2":"test2"}],"otherParam":"value2"}
Info:   JSON2: {}

我要说的是,第二个JSON是{"test1":"test1"}。我错了?

问题似乎是链接到.build()函数,该函数将添加到HASH_MAP中的元素的所有valueMap设置为null (参见图像)。

如何将HASH_MAP中的值保持不变?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-03 22:05:17

在从一个build()中对一个JsonObject进行JsonObject处理之后,构建器就可以被允许重用了。为了说明这一点:

代码语言:javascript
复制
JsonObjectBuilder b = Json.createObjectBuilder();
b.add("foo", "bar");
JsonObject o = b.build();
JsonObject p = b.build();
System.out.println(o.toString()); // {"foo":"bar"}
System.out.println(p.toString()); // {}

当你做的时候

代码语言:javascript
复制
l1.add(l.getValue()); // l.getValue() is (JsonObjectBuilder) one at some time

build()one上被隐式调用,因此它是空的。

然后在这里:

代码语言:javascript
复制
System.out.println("JSON2: " + HASH_MAP.get("one").build().toString());

构建空JsonObject的表示形式。

为了避免这种情况,您可以在hashmap中存储JsonObjects而不是JsonObjectBuilders:

代码语言:javascript
复制
Map<String, JsonObject> HASH_MAP = new HashMap<>();

JsonObjectBuilder one = Json.createObjectBuilder();
one.add("test1","test1");
HASH_MAP.put("one", one.build());

JsonObjectBuilder two = Json.createObjectBuilder();
two.add("test2","test2");
HASH_MAP.put("two", two.build());

JsonObjectBuilder toReturn = Json.createObjectBuilder();
JsonArrayBuilder l1 = Json.createArrayBuilder();
for (Map.Entry<String, JsonObject> l : HASH_MAP.entrySet()) {
    l1.add(l.getValue());
}

toReturn.add("l1", l1);
toReturn.add("otherParam", "value2");
String strJSON = toReturn.build().toString();
System.out.println("JSON1: " + strJSON);
System.out.println("JSON2: " + HASH_MAP.get("one").toString());

现在它应该像你期望的那样起作用了。

票数 5
EN

Stack Overflow用户

发布于 2016-02-03 22:13:50

请记住,对build()的调用刷新了存储在对象one JSonObjectBuilder中的值,因此您只能调用一次方法build(),如果再次调用它,则可以获得空JSonObject的表示形式。例如:

代码语言:javascript
复制
one.add("test1","test1");   
System.out.println(one.build())
System.out.println(one.build())

产出:

代码语言:javascript
复制
{"test1":"test1"}
{}

如果你真的想再次调用它,你必须再次添加你想要的价值。例如:

代码语言:javascript
复制
one.add("test1","test1");
System.out.println(one.build())
one.add("test1","test1")
System.out.println(one.build())

产出:

代码语言:javascript
复制
{"test1":"test1"}
{"test1":"test1"}

正如@Ctx所述,您可以将映射JsonObjects而不是JsonObjectBuilders放在映射中,因此将方法JsonObject ()的调用返回的JsonObject作为映射的值。

例如:

代码语言:javascript
复制
HASH_MAP.put("one", one.build());
票数 3
EN

Stack Overflow用户

发布于 2017-06-14 07:52:57

如前所述,在调用build()时,提供的JsonObjectBuilder实现会刷新。

最好的解决方案是基于JsonObjectBuilder接口实现您自己的非刷新构建器:

代码语言:javascript
复制
public final class NfJsonObjectBuider implements JsonObjectBuilder {

    private Map<String, Object> values = new LinkedHashMap<>();

    @Override
    public JsonObjectBuilder add(String name, JsonValue value) {
        this.values.put(name, value);
        return this;
    }

    @Override
    public JsonObjectBuilder add(String name, String value) {
        this.values.put(name, value);
        return this;
    }

    @Override
    public JsonObjectBuilder add(String name, BigInteger value) {
        this.values.put(name, value);
        return this;
    }
    //other add(...) methods with the same implementation

    @Override
    public JsonObject build() {
        //HERE: reuse their building logic.
        final JsonObjectBuilder builder = Json.createObjectBuilder();
        for(final Entry<String, Object> pair : this.values.entrySet()) {
            this.addToBuilder(pair, builder);
        }
        return builder.build();
    }

    private void addToBuilder(Entry<String, Object> pair, JsonObjectBuilder 
 builder) {
        if(pair.getValue() instanceof JsonValue) {
            builder.add(pair.getKey(), (JsonValue) pair.getValue());
        }
        if(pair.getValue() instanceof String) {
            builder.add(pair.getKey(), (String) pair.getValue());
        }
        if(pair.getValue() instanceof Boolean) {
            builder.add(pair.getKey(), (Boolean) pair.getValue());
        }
        //A couuple more ifs to cover all the add(...) methods.
    }
}

这里的整篇文章:http://www.amihaiemil.com/2017/06/14/non-flushable-jsonobjectbuilder.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35187129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档