Класс десериализации свойств с использованием Jackson fastxml
Я пытаюсь использовать Джексона с fastxml (против Codehaus), чтобы получить некоторые данные, которые я храню в mongoDb десериализованным. Запрос возвращает правильную строку json, но я продолжаю получать эту ошибку, что мы пытаемся преобразовать в объект:
Can not deserialize instance of java.lang.String out of START_OBJECT token Properties("property1")
Учебный класс:
package com.sharecare.service.segment;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.jamconsultg.jamplatform.domain.segmentation.Segment;
import java.util.List;
import java.util.Properties;
/**
* Created by wawada on 1/15/16.
*/
public class SubSkyScraper{
@JsonProperty("_id")
private String id;
private String name;
private Properties properties;
@JsonProperty("_segments")
private List<Segment> segments;
public SubSkyScraper() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public List<Segment> getSegments() {
return segments;
}
public void setSegments(List<Segment> segments) {
this.segments = segments;
}
}
Тестовое задание:
package com.sharecare.service.segment;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jamconsultg.jamplatform.domain.segmentation.Segment;
import com.sharecare.segment.SkyScraper;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
/**
* Created by wawada on 1/15/16.
*/
public class ObjectMapperTest {
@Test
public void testGettingTheObject(){
String json = "{\n" +
"\"_id\": \"objectid\" ,\n" +
"\"_segments\" : [ \"global\"] , \n" +
"\"name\" : \"sc\" , \n" +
"\"properties\" : { \n" +
" \"property1\": {\n" +
" \"property2\" : \"value1\"\n" +
" },\n" +
" \"property3\" : { \"property4\": \"value2\"} , \n" +
" \"property5\": {\n" +
" \"property6\" : { \n" +
" \"property7\": \"value3\" , \n" +
" \"property8\": \"value4\"\n" +
" }\n" +
"}\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
try {
objectMapper.readValue(json, SubSkyScraper.class);
} catch (IOException e) {
e.printStackTrace();
}
}
}
выход:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: {
"_id": "objectid" ,
"_segments" : [ "global"] ,
"name" : "sc" ,
"properties" : {
"property1": {
"property2" : "value1"
},
"property3" : { "property4": "value2"} ,
"property5": {
"property6" : {
"property7": "value3" ,
"property8": "value4"
}
}
}; line: 6, column: 5] (through reference chain: com.sharecare.service.segment.SubSkyScraper["properties"]->java.util.Properties["property1"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:857)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:62)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:495)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:341)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
at com.sharecare.service.segment.ObjectMapperTest.testGettingTheObject(ObjectMapperTest.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
JSON, сохраненный в mongodb, имеет следующую структуру:
{
"_id": "objectid" ,
"_segments" : [ "global "] ,
"name" : "sc" ,
"properties" : {
"property1": {
"property2" : "value1"
},
"property3" : { "property4": "value2"} ,
"property5": {
"property6" : {
"property7": "value3" ,
"property8": "value4"
}
}
}
Как я могу заставить Джексона правильно десериализовать свойства?
PS: это работало безупречно с Codehaus
0 ответов
Вот мой подход:
Я использую собственный десериализатор, как показано ниже:
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
public class PropertiesDeserializer extends StdDeserializer<Properties> {
private static final long serialVersionUID = 2743004642083542567L;
public PropertiesDeserializer() {
this(null);
}
public PropertiesDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Properties deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonDeserializer<Object> mapDeserializer = findDeserializer(ctxt, ctxt.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class), null);
@SuppressWarnings("unchecked")
Map<String,Object> rawValue = (Map<String, Object>) mapDeserializer.deserialize(jp, ctxt);
if (rawValue == null) {
return null;
}
Properties mappedValue = new Properties();
rawValue.forEach((key, value) -> mappedValue.put(key, value));
return mappedValue;
}
}
а затем зарегистрируйте его в своем ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Properties.class, new PropertiesDeserializer());
mapper.registerModule(simpleModule);
Если вы хотите проанализировать вложенный java.util.Properties, вы можете сделать это в методе десериализации при повторении через карту rawValue