我设法将Jackson配置为序列化一个类,只需使用
就可以在类中的私有字段上没有任何getter或注释objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
但我没有设法将这个非静态类的JSON字符串设置为反序列化为没有任何参数化构造函数或setter的对象。这有可能 - 我认为它应该通过反思但我不确切地知道如何......
以下是需要通过的两项测试,以实现我的目标:
public class ObjectMapperTest {
private ObjectMapper mapper;
@Before
public void init() {
mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
}
@Test
public void serialize() throws Exception {
Payload payloadToSerialize = new Payload();
payloadToSerialize.data = "testData";
String serializedPayload = mapper.writeValueAsString(payloadToSerialize);
assertThat(serializedPayload, is("{\"data\":\"testData\"}"));
// --> OK
}
@Test
public void deserialize() throws Exception {
Payload deserializedPayload = mapper.readValue("{\"data\":\"testData\"}", Payload.class);
assertThat(deserializedPayload.data, is("testData"));
// com.fasterxml.jackson.databind.JsonMappingException:
// No suitable constructor found for type [simple type, class ...ObjectMapperTest$Payload]:
// can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
// at [Source: {"data":"testData"}; line: 1, column: 2]
}
public class Payload {
private String data;
public Payload() {
// empty constructor for Jackson
}
}
}
使Payload类静态将修复测试,但静态类不是我的选项,因为我不使用项目中的内部有效负载类。任何想法如何通过对象映射器配置更改来修复它?
修改的 当我在Spring MVC应用程序中使用Jackson对象映射器来序列化/反序列化时,我需要一个只改变或扩展对象映射器配置的解决方案。
答案 0 :(得分:2)
您可以编写自己的反序列化器来解析JSON并创建Payload
的实例,然后使用反射设置data
值。
例如:
@Before
public void init() {
mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
mapper.registerModule(
new SimpleModule()
.addDeserializer(Payload.class, new JsonDeserializer<Payload>() {
@Override
public Payload deserialize(JsonParser parser, DeserializationContext ctx)
throws IOException, JsonProcessingException {
JsonNode obj = parser.readValueAsTree(); // Read the JSON as a node
Payload payload = new Payload();
if (obj.isObject() && obj.has("data")) { // The node is an object and has a "data" field
try {
// Use reflection to set the value
Field dataField = payload.getClass().getDeclaredField("data");
dataField.setAccessible(true);
dataField.set(payload, obj.get("data").asText());
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
throw new IOException("Reflection error", ex);
}
}
return payload;
}
}));
}
修改:如果您想要更多内容&#34; generic&#34;您可以尝试自己创建实例并更改所有字段的可访问性。然后你告诉Jackson使用JSON更新值。
public <T> T deserialize(final String json, final T instance) throws Exception {
for (Field field : instance.getClass().getDeclaredFields()) {
field.setAccessible(true);
}
mapper.readerForUpdating(instance).readValue(json);
return instance;
}
@Test
public void deserializeUpdate() throws Exception {
Payload deserializedPayload = deserialize("{\"data\":\"testData\"}", new Payload());
assertThat(deserializedPayload.data, is("testData"));
}
我在你的Payload课上测试了这个,也许它不适用于更复杂的对象。