为了账号安全,请及时绑定邮箱和手机立即绑定

如何在从杰克逊中的字符串构造 JsonNode 时更改其值

如何在从杰克逊中的字符串构造 JsonNode 时更改其值

烙印99 2022-09-14 16:21:04
我有一个 JSON 字符串,我想在使用杰克逊库构造 JsonNode 时更改该值。例如:-input: {"name":"xyz","price":"90.00"}output:{"name":"xyz-3","price":90.90}我创建了自己的 JsonFactory 并传递了自己的解析器。但我只能更改键,而不能更改与键关联的值。法典:private static ObjectMapper create() {        ObjectMapper objectMapper = new ObjectMapper(new JsonFactory() {            @Override            protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException {                return new MyParser(super._createParser(data, offset, len, ctxt));            }            @Override            protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException {                return new MyParser(super._createParser(in, ctxt));            }            @Override            protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException {                return new MyParser(super._createParser(r, ctxt));            }            @Override            protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt, boolean recyclable)                    throws IOException {                return new MyParser(super._createParser(data, offset, len, ctxt, recyclable));            }        });private static final class MyParser extends JsonParserDelegate {        private MyParser(JsonParser d) {            super(d);        }        @Override        public String getCurrentName() throws IOException, JsonParseException {            ....        }        @Override        public String getText() throws IOException, JsonParseException {           ...        }        @Override        public Object getCurrentValue() {            ...        }        @Override        public String getValueAsString() throws IOException {            ...        }在这种情况下,当调用 readTree 方法或未调用方法时,我无法在创建 JsonNode 本身时更改值。此外,json 字符串也可以不同。基本上,我想从字符串构造一个 JsonNode。因此,在这里绑定到特定的模式/bean 不是一个好的选择。如何解决这个问题?蒂亚getCurrentValuegetValueAsString
查看完整描述

2 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

编辑:和 之间有细微的区别。

同时能够区分和与2.7.*2.9.*2.9.*doublefloat


getDoubleValue()

getFloatValue()

而是只使用2.7.*


getDoubleValue()

即使是代币。

因此,您需要决定是否要保持逆向兼容性。ID_NUMBER_FLOAT


您也可以覆盖两者,就像我在这里所做的那样。


这就是您的定制所需的全部内容MyParser


static class MyParser extends JsonParserDelegate {

    MyParser(final JsonParser delegate) {

        super(delegate);

    }


    @Override

    public String getText() throws IOException {

        final String text = super.getText();


        if ("name".equals(getCurrentName())) {

            return text + "-3";

        }


        return text;

    }


    @Override

    public JsonToken nextToken() throws IOException {

        if ("price".equals(getCurrentName())) {

            // Advance token anyway

            super.nextToken();

            return JsonToken.VALUE_NUMBER_FLOAT;

        }


        return super.nextToken();

    }


    @Override

    public int getCurrentTokenId() {

        try {

            if ("price".equals(getCurrentName())) {

                return JsonTokenId.ID_NUMBER_FLOAT;

            }

        } catch (final IOException e) {

            //

        }


        return super.getCurrentTokenId();

    }


    @Override

    public NumberType getNumberType() throws IOException {

        if ("price".equals(getCurrentName())) {

            return NumberType.FLOAT;

        }


        return super.getNumberType();

    }


    @Override

    public float getFloatValue() throws IOException {

        return Float.parseFloat(getValueAsString("0")) + 0.09F;

    }


    @Override

    public double getDoubleValue() throws IOException {

       return Double.parseDouble(getValueAsString("0")) + 0.09D;

    }

}

输出:{"name":"xyz-3","price":90.09}


您的代码看起来很好,并且已经过测试并;)


查看完整回答
反对 回复 2022-09-14
?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

您是否真的确定,关于关注点分离,在解析的数据中混合解析和更改是一个好主意?

如果您仍然想这样做,则可以使用自定义反序列化程序,并按照所需的方式处理所需的字段名称和类型,例如:

class CustomDeserializer extends StdDeserializer<Entity> {

    public CustomDeserializer(Class<Entity> t) {

        super(t);

    }


    @Override

    public Entity deserialize(JsonParser jp, DeserializationContext dc) throws IOException {

        String name = null;

        float price = 0;


        JsonToken currentToken = null;

        while ((currentToken = jp.nextValue()) != null) {

            switch (currentToken) {

                case VALUE_STRING:

                    switch (jp.getCurrentName()) {

                        case "name":

                            name = jp.getText() + "-3"; // change this text to whatever you want;

                            break;

                        case "price":

                            price = Float.parseFloat(jp.getText()); // parse

                            break;

                        default:

                            break;

                    }

                    break;

                default:

                    break;

            }

        }

        return new Entity(name, price);

    }

}

注册自定义反序列化程序后,它可以在您想要的任何对象映射器上运行:


    @Test

    public void customDeserialization() throws IOException {

        // given

        ObjectMapper mapper = new ObjectMapper();

        SimpleModule module = new SimpleModule();

        module.addDeserializer(Entity.class, new CustomDeserializer(Entity.class));

        mapper.registerModule(module);


        // when

        Entity entity = mapper.readValue("{\"name\":\"xyz\",\"price\":\"90.00\"}", Entity.class);


        // then

        assertThat(entity.getName()).isEqualTo("xyz-3");

        assertThat(entity.getPrice()).isEqualTo(90f);

    }


查看完整回答
反对 回复 2022-09-14
  • 2 回答
  • 0 关注
  • 134 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信