不可变的Jackson ObjectWriter

时间:2017-03-08 09:03:11

标签: java json jackson

我想在多个不同的上下文中(de-)序列化JSON,这些上下文需要在多个线程中略有不同的Jackson配置。根据Web和类注释中的资源,这应该可以使用从ObjectMapper构造的ObjectWriter和ObjectReader,它具有" base"组态。但是,我还没有成功地从ObjectMapper构建一个不可变的ObjectWriter - 它似乎与mapper一起改变了它的配置。

这是重新配置WRITE_NUMBERS_AS_STRINGS的示例。请将此视为"只是一个例子" WRT我需要ObjectReader和ObjectWriter的解决方案,以及各种配置对象,如@ JacksonInject' ed值,而不仅仅是低级JSON格式选项。

public class Main3 {

    public static void main(String[] args) throws Exception {
        test(false);
        test(true);
    }

    private static void test(boolean enable) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
        ObjectWriter w1 = mapper.writer();
        if (enable) {
            mapper.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
        }
        ObjectWriter w2 = mapper.writer();
        Bean b = new Bean();
        b.setX(42);
        System.out.println(w1.writeValueAsString(b));
        System.out.println(w2.writeValueAsString(b));
    }

    public static class Bean {

        private int x;

        /**
         * Getter method.
         *
         * @return the x
         */
        public int getX() {
            return x;
        }

        /**
         * Setter method.
         *
         * @param x the x
         */
        public void setX(int x) {
            this.x = x;
        }

    }

}

正如您所看到的,我运行相同的测试两次,每次从同一个ObjectMapper创建两个ObjectWriters并使用每个ObjectWrite序列化一个测试bean。在第二次运行中,我为第二个写入器启用了WRITE_NUMBERS_AS_STRINGS。这似乎也影响了第一位作家。

预期产出:

{"x":42}
{"x":42}
{"x":42}
{"x":"42"}

实际输出:

{"x":42}
{"x":42}
{"x":"42"}
{"x":"42"}

还有什么需要将ObjectWriter与ObjectMapper分离吗?不用说,基于这个违反线程安全的示例构建一个示例应该是微不足道的,更不用说ObjectWriter显然不是不可变的。

2 个答案:

答案 0 :(得分:2)

文档确实声称读者和作者是不可改变的。如果您发现某些情况不属于您,则应将其报告为错误。

与此同时,您可以复制DB db = mongo.getDB("sample"); DBCollection table = db.getCollection("samplecollection"); DBCursor cursor2 = table.find(); ,然后从副本中创建ObjectMapper

答案 1 :(得分:0)

对于简短的回答,问题是通过JsonFactory应用的基础ObjectMapper的任何更改确实会泄漏。不是因为ObjectWriter(或ObjectReader)是可变的,而是因为它们共享可变工厂。

但是:使用with(Feature) / without(Feature)方法可以采用另一种方法避免此类可见更改:

w = w.with(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);    // 要么    w = w.without(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);

通过修改构造的JsonGenerator来工作,而不是重新构造构造生成器的JsonFactory