Я пытаюсь включить необработанный 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 статическим классом, который вызывал другую ошибку.
источник
После ответа @StaxMan я сделал следующие работы как шарм:
И, чтобы быть верным первоначальному вопросу, вот рабочий тест:
источник
getJson()
таки возвращаетсяString
. Если он просто вернет значениеJsonNode
, установленное через сеттер, он будет сериализован по желанию, не так ли?node.asText()
возвращает пустое значение напротивtoString()
.Я смог сделать это с помощью специального десериализатора (вырезано и вставлено отсюда )
источник
@JsonRawValue
@JsonSetter может помочь. См. Мой образец («данные» должны содержать неанализируемый JSON):
источник
В дополнение к отличному ответу Роя Трулава , вот как ввести настраиваемый десериализатор в ответ на появление :
@JsonRawValue
источник
Это проблема ваших внутренних классов.
Pojo
Класс представляет собой не статический внутренний класс вашего тестового класса, и Джексон не может экземпляр этого класса. Таким образом, он может сериализоваться, но не десериализоваться.Переопределите свой класс следующим образом:
Обратите внимание на добавление
static
источник
Это простое решение сработало для меня:
Итак, я смог сохранить необработанное значение JSON в переменной rawJsonValue, и тогда не было проблем с десериализацией его (как объекта) с другими полями обратно в JSON и отправкой через мой REST. Использование @JsonRawValue не помогло мне, потому что сохраненный JSON был десериализован как String, а не как объект, и это было не то, что я хотел.
источник
Это работает даже в сущности JPA:
В идеале ObjectMapper и даже JsonFactory взяты из контекста и настроены так, чтобы правильно обрабатывать ваш JSON (например, стандартные или с нестандартными значениями, такими как «Infinity» с плавающей точкой).
источник
JsonNode.toString()
документации.Method that will produce developer-readable representation of the node; which may <b>or may not</b> be as valid JSON.
Так что на самом деле это очень рискованная реализация.JsonNode.asText()
внутреннее значение и выводит Infinity и другие нестандартные значения JSON.Вот полный рабочий пример того, как использовать модули Джексона для
@JsonRawValue
работы в обоих направлениях (сериализация и десериализация):Затем вы можете зарегистрировать модуль после создания
ObjectMapper
:источник
org.codehaus.jackson
пакета, не осознавая этого. Убедитесь, что весь ваш импорт исходит изcom.fasterxml.jackson
.У меня была такая же проблема. Я нашел решение в этом посте: Разобрать дерево JSON до простого класса с помощью Джексона или его альтернатив
Проверьте последний ответ. Благодаря определению настраиваемого установщика для свойства, которое принимает JsonNode в качестве параметра и вызывает метод toString на jsonNode для установки свойства String, все работает.
источник
Использование объекта прекрасно работает в обоих направлениях ... Этот метод имеет небольшие накладные расходы на десериализацию необработанного значения в два раза.
RawHello.java
RawJsonValue.java
источник
У меня была аналогичная проблема, но я использовал список с большим количеством JSON itens (
List<String>
).Я управлял сериализацией с помощью
@JsonRawValue
аннотации. Но для десериализации мне пришлось создать собственный десериализатор на основе предложения Роя.Ниже вы можете увидеть мой десериализатор "Список".
источник