Как включить необработанный JSON в объект, используя Джексона? - PullRequest
93 голосов
/ 24 января 2011

Я пытаюсь включить необработанный JSON в объект Java, когда объект (де) сериализован с использованием Джексона. Чтобы проверить эту функциональность, я написал следующий тест:

public static class Pojo {
    public String foo;

    @JsonRawValue
    public String bar;
}

@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {

    String foo = "one";
    String bar = "{\"A\":false}";

    Pojo pojo = new Pojo();
    pojo.foo = foo;
    pojo.bar = bar;

    String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";

    ObjectMapper objectMapper = new ObjectMapper();
    String output = objectMapper.writeValueAsString(pojo);
    System.out.println(output);
    assertEquals(json, output);

    Pojo deserialized = objectMapper.readValue(output, Pojo.class);
    assertEquals(foo, deserialized.foo);
    assertEquals(bar, deserialized.bar);
}

Код выводит следующую строку:

{"foo":"one","bar":{"A":false}}

JSON - это именно то, как я хочу, чтобы вещи выглядели. К сожалению, код завершается с ошибкой при попытке прочитать JSON обратно в объект. Вот исключение:

org.codehaus.jackson.map.JsonMappingException: Невозможно десериализовать экземпляр java.lang.String из маркера START_OBJECT. в [Источник: java.io.StringReader@d70d7a; строка: 1, столбец: 13] (через цепочку ссылок: com.tnal.prism.cobalt.gather.testing.Pojo ["bar"])

Почему Джексон прекрасно работает в одном направлении, но не работает при движении в другом направлении? Похоже, что он должен быть в состоянии взять свой собственный вывод в качестве ввода снова. Я знаю, что я пытаюсь сделать, это неортодоксально (общий совет - создать внутренний объект для bar, который имеет свойство с именем A), но я вообще не хочу взаимодействовать с этим JSON. Мой код действует как проход для этого кода - я хочу взять этот JSON и снова отправить его обратно, не затрагивая ничего, потому что, когда JSON изменяется, я не хочу, чтобы мой код нуждался в изменениях.

Спасибо за совет.

EDIT: сделал Pojo статическим классом, который вызывал другую ошибку.

Ответы [ 12 ]

1 голос
/ 23 мая 2016

Использование объекта прекрасно работает в обоих направлениях ... Этот метод имеет некоторые накладные расходы на десериализацию необработанного значения в два раза.

ObjectMapper mapper = new ObjectMapper();
RawJsonValue value = new RawJsonValue();
value.setRawValue(new RawHello(){{this.data = "universe...";}});
String json = mapper.writeValueAsString(value);
System.out.println(json);
RawJsonValue result = mapper.readValue(json, RawJsonValue.class);
json = mapper.writeValueAsString(result.getRawValue());
System.out.println(json);
RawHello hello = mapper.readValue(json, RawHello.class);
System.out.println(hello.data);

RawHello.java

public class RawHello {

    public String data;
}

RawJsonValue.java

public class RawJsonValue {

    private Object rawValue;

    public Object getRawValue() {
        return rawValue;
    }

    public void setRawValue(Object value) {
        this.rawValue = value;
    }
}
1 голос
/ 19 апреля 2013

У меня была точно такая же проблема.Я нашел решение в этом посте: Разобрать дерево JSON для простого класса, используя Джексона или его альтернативы

Проверьте последний ответ.Определив пользовательский установщик для свойства, которое принимает JsonNode в качестве параметра и вызывает метод toString в jsonNode для установки свойства String, все это работает.

...