Java Jackson用变量插值反序列化

Java Jackson用变量插值反序列化,java,json,jackson,token,interpolation,Java,Json,Jackson,Token,Interpolation,如何自定义Jackson以反序列化包含${token}的值 下面是我想从中添加的Functionality示例: 您可以基于默认值注册,该默认值将在反序列化后插入变量 但是,正如在评论中指出的那样,这对非字符串类型(如文件和URL)不起作用。更好的方法是通过传递自定义的JsonFactory来覆盖JsonParser的getText()和getValueAsString()方法 以下是一个例子: public class JacksonInterpolateString { static

如何自定义Jackson以反序列化包含
${token}
的值

下面是我想从中添加的Functionality示例:

您可以基于默认值注册,该默认值将在反序列化后插入变量

但是,正如在评论中指出的那样,这对非字符串类型(如文件和URL)不起作用。更好的方法是通过传递自定义的
JsonFactory
来覆盖
JsonParser
getText()
getValueAsString()
方法

以下是一个例子:

public class JacksonInterpolateString {
    static final String JSON = "{ \"file\":\"${sys:user.home}/path/to/my_file\" }";

    public static class Bean {
        public File file;

        @Override
        public String toString() {
            return file.toString();
        }
    }

    private static class MyJsonParser extends JsonParserDelegate {

        public MyJsonParser(final JsonParser d) {
            super(d);
        }

        @Override
        public String getText() throws IOException {
            final String value = super.getText();
            if (value != null) {
                return interpolateString(value);
            }
            return value;
        }

        @Override
        public String getValueAsString() throws IOException {
            return getValueAsString(null);
        }

        @Override
        public String getValueAsString(final String defaultValue) throws IOException {
            final String value = super.getValueAsString(defaultValue);
            if (value != null) {
                return interpolateString(value);
            }
            return null;
        }
    }

    private static class MyMappingJsonFactory extends MappingJsonFactory {
        @Override
        protected JsonParser _createParser(
                final char[] data,
                final int offset,
                final int len,
                final IOContext ctxt,
                final boolean recyclable)
                throws IOException {
            return new MyJsonParser(super._createParser(data, offset, len, ctxt, recyclable));
        }

        @Override
        protected JsonParser _createParser(final Reader r, final IOContext ctxt)
                throws IOException {
            return new MyJsonParser(super._createParser(r, ctxt));
        }

    }

    private static String interpolateString(final String value) {
        return value.replace("${sys:user.home}", "/home/user");
    }

    public static void main(String[] args) throws IOException {
        final JsonFactory factory = new MyMappingJsonFactory();
        final ObjectMapper mapper = new ObjectMapper(factory);
        System.out.println(mapper.readValue(JSON, Map.class));
        System.out.println(mapper.readValue(JSON, Bean.class));
    }

}
输出:

{file=/home/user/path/to/my_file}
/home/user/path/to/my_file

他的解决方案仅在我想反序列化
字符串时有效,但如何在每个反序列化器类型(即路径)上应用转换?我想我必须创建一个
JsonParser
来覆盖
getText
getValusAsString
?@gulecroc很好!我已经用你的建议更新了我的答案。听起来不错!我被重写
JsonParser
卡住了,不知道
JsonParserDelegate
!很抱歉没有足够的声誉来投票。。。所以+1@GuillaumeLecroc我很高兴它起作用了!这实际上是一个很好的问题,(我希望)是一个很好的答案,它可能会帮助其他人。我相信你应该能够接受这个答案,即使你没有什么名声。以下是此网站的链接:
{file=/home/user/path/to/my_file}
/home/user/path/to/my_file