2015-02-16 5 views
0

Я пытаюсь использовать Джексон как универсальный механизм сериализации вместо сериализации Java. инициализацией картографа следующим образом:Deserializing Java массивы с Jackson

objectMapper = new ObjectMapper(); 
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

Все виды информации в хранятся в формате JSON, так что я в состоянии читать и писать все свои объекты обратно с:

objectMapper.readValue(json, Object.class) 

Я имею проблемы при попытке сериализации, а затем десериализации java-массивов. Поскольку Jackson не сохраняет тип массива в JSON, он не работает на этапе десериализации. В следующем коде:

String [] strings = {"A", "B", "C"}; 
    try { 
     String json = objectMapper.writeValueAsString(strings); 
     String [] stringsBack = (String [])objectMapper.readValue(json, Object.class); 
     if (!strings.equals(stringsBack)) { 
      System.err.println("ERROR, stringsBack not the same!!!\n\n"); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

JSON будет установлен на "[" A " "B", "C"]", но на десериализации я получаю следующее исключение:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found 
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver._typeFromId(ClassNameIdResolver.java:66) 
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:48) 
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:157) 
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:94) 
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:68) 
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:494) 
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:42) 
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560) 
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576) 
at Main.run(Main.java:86) 

Есть способ проинструктировать Джексона хранить информацию о типах массивов java, а также в JSON? Мой механизм сериализации является общим и не знает заранее, какой тип он будет читать из строки JSON.

+0

Есть ли причина, что вы не используете 'objectMapper.readValue (JSON, String [] класс.)'? Вы сказали Джексону десериализовать объект, и, конечно, он понятия не имеет, какой тип объекта он имеет. – immibis

+0

Причина в том, что мне нужно иметь возможность хранить и читать объекты из строк без дополнительного знания их типа. Для всех остальных сценариев он работает, поскольку имена классов хранятся в JSON. Я ищу флаг, который даст указание Джексону хранить типы массивов java в строке, а затем он сможет найти этот тип сам по себе. –

ответ

1

Лучшее решение, которое я нашел для теперь проверять перед сериализации, если объект является массивом (Class.isArray), а затем делать сериализацию:

TypeReference ref = new TypeReference<List[]>() { }; 
String json = objectMapper.writerFor(ref).writeValueAsString(strings); 

Это добавит тип массива в JSON и включите чтение.

0

Правильный путь:

String[] strings = { "A", "B", "C" }; 
ObjectMapper mapper = new ObjectMapper(); 
String json = mapper.writeValueAsString(strings); 
List<String> data = mapper.readValue(json, 
     mapper.getTypeFactory().constructCollectionType(List.class, String.class)); 
for (String string : data) { 
    System.out.println(string); 
} 
0

Есть Multiple проблема с кодом.

1) Во-первых, давайте посмотрим, почему исключение

Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found 

выше ошибка говорит, что он не нашел какого-либо класса и относится А, как недопустимый идентификатор типа «А ', кажется, как вопрос в Json.

Проблема в том, что из линий

objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

Это позволило по умолчанию Typing для всех Non Заключительным типов. Настройка по умолчанию печатает тип объекта с фактическим значением объекта, таким образом, позволяет десериализацию в один и тот же тип. Объявление NON_FINAL не будет добавлять «естественные» типы, такие как String.

и

String [] stringsBack = (String [])objectMapper.readValue(json, Object.class); 

Теперь во время десериализации Json [ "A", "B", "C"], то десериализатор не знал WAHT объект по JSON должен быть преобразован также и взяли в качестве класса Тип и попытался найти класс, который он не получил.

2) Комментируя первой линии, вероятно, дать ClassCastException потому

objectMapper.readValue(json, Object.class); 

будет возвращать объект ArrayList, и он не может быть приведен к String [].

3) !strings.equals(stringsBack) всегда возвращает true как строки и строки. Оба являются разными объектами String [].

исправляющих все вещи, следующий код будет работать

ObjectMapper objectMapper = new ObjectMapper(); 
    //You can remove the below line if Default Typing is not Required. 
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 
    String[] strings = { "A", "B", "C" }; 
    try 
    { 
     String json = objectMapper.writeValueAsString(strings); 
     System.out.println(json); 
     String[] stringsBack = (String[]) objectMapper.readValue(json, new TypeReference<String[]>() 
     {}); 
     if (!Arrays.equals(strings, stringsBack)) 
     { 
      System.err.println("ERROR, stringsBack not the same!!!\n\n"); 
     } 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
+0

Спасибо за ответ, но решение не отвечает требованиям, чтобы читать данные без какого-либо знания типа объекта внутри. –

Смежные вопросы