Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson deserialize with variable interpolation

How to custom Jackson to deserialize a value that contains a ${token} ?

Here is an example of the functionnality that i want to add from the Apache Commons Configuration variable interpolation :

{
    "file" = "${sys:user.home}/path/to/my_file"
}
like image 236
Guillaume Lecroc Avatar asked Dec 18 '25 19:12

Guillaume Lecroc


1 Answers

You can register a custom string deserialiser based on the default which would interpolate the variables after the deserialisation.

But, as was pointed out in the comments, that would not work for the non-String types such as File and URLs. The better idea is to override the getText() and getValueAsString() methods of the JsonParser by passing a custom JsonFactory.

Here is an example:

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));
    }

}

Output:

{file=/home/user/path/to/my_file}
/home/user/path/to/my_file
like image 110
Alexey Gavrilov Avatar answered Dec 21 '25 09:12

Alexey Gavrilov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!