我使用jackson-databind版本2.12.3来序列化应该返回的对象的返回,如下所示:
{
"field1":"value1",
"field2":"value2",
"links":{
"field":{
"href":"/link"
},
"test":{
"href":"/test"
}
}
}我的课程是:
public class HrefType {
private String href = null;
...
}public class Link extends HashMap<String, HrefType> {
private HrefType field = null;
...
}public class MyObject {
private String field1 = null;
private String field2 = null;
private Link links = null;
...
}返回的是myObject:
MyObject myObject = new MyObject();
myObject.setField1("value1");
myObject.setField2("value2");
Link link = new Link();
link.setField(new HrefType().href("/link"));
link.put("test",new HrefType().href("/test"));
myObject.setLinks(link);但是,对于默认的ObjectMapper,"link.setField“将被忽略,返回的json是:
{
"field1":"value1",
"field2":"value2",
"links":{
"test":{
"href":"/test"
}
}
}我尝试用JsonSerializer进行一些测试,但无法对所有扩展HashMap的类执行一些通用的操作(这些类是从BerlinGroup的PSD2 YAML生成的,因此我不想更改生成的类)。
是否有一种通用的方法来做到这一点,或者我应该为每个扩展HashMap的类创建一个序列化类?
发布于 2021-06-09 09:07:39
基于this answer,我开发了一种为扩展Map的所有对象创建的通用方法:
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import org.springframework.util.ReflectionUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class MyClassSerializer extends JsonSerializer<Object> {
private final JsonSerializer<Object> defaultSerializer;
public MyClassSerializer(JsonSerializer<Object> defaultSerializer) {
this.defaultSerializer = (defaultSerializer);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void serialize(Object src, JsonGenerator gen, SerializerProvider provider) throws IOException {
Field[] fields = src.getClass().getDeclaredFields();
for (Field field : fields) {
try {
boolean fieldAccessible = field.isAccessible();
field.setAccessible(true);
Object object = ReflectionUtils.getField(field, src);
if (object != null && object instanceof Map) {
Field[] fieldsMap = object.getClass().getDeclaredFields();
Map map = (Map) object;
for (Field fieldMap : fieldsMap) {
boolean fieldMapAccessible = fieldMap.isAccessible();
fieldMap.setAccessible(true);
Object fieldObject = ReflectionUtils.getField(fieldMap, object);
if (fieldObject != null) {
map.put(fieldMap.getName(), fieldObject);
}
fieldMap.setAccessible(fieldMapAccessible);
}
}
field.setAccessible(fieldAccessible);
} catch (Exception e) {
e.printStackTrace();
}
}
defaultSerializer.serialize(src, gen, provider);
}
@Override
public Class<Object> handledType() {
return Object.class;
}
}它贯穿所有字段,当我找到一个从Map扩展的字段时,我遍历这个字段的所有字段,并将其添加到Map中,忽略对象的字段,所以序列化程序完美地工作。
编辑:要正确地反序列化,我执行以下操作:
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import org.springframework.util.ReflectionUtils;
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.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ResolvableDeserializer;
@SuppressWarnings("rawtypes")
public class MyClassDeserializer extends JsonDeserializer implements ResolvableDeserializer {
private JsonDeserializer defaultDeserializer;
protected MyClassDeserializer(JsonDeserializer deserializer) {
this.defaultDeserializer = deserializer;
}
@SuppressWarnings("unchecked")
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Object obj = defaultDeserializer.deserialize(p, ctxt);
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
try {
boolean fieldAccessible = field.isAccessible();
field.setAccessible(true);
Object object = ReflectionUtils.getField(field, obj);
if (object != null && object instanceof Map) {
Field[] fieldsMap = object.getClass().getDeclaredFields();
Map map = (Map) object;
for (Object key : map.keySet()) {
for (Field fieldMap : fieldsMap) {
if (fieldMap.getName().equals((String) key)) {
if (fieldMap.getName().equalsIgnoreCase("serialVersionUID")) {
continue;
}
boolean fieldMapAccessible = fieldMap.isAccessible();
fieldMap.setAccessible(true);
Object fieldObject = ReflectionUtils.getField(fieldMap, object);
if (fieldObject == null) {
fieldMap.set(object, map.get(key));
map.replace(key, null);
}
fieldMap.setAccessible(fieldMapAccessible);
}
}
}
Object[] keys = map.keySet().toArray();
for (int i = 0; i < keys.length; i++) {
if(map.get(keys[i])==null) {
map.remove(keys[i]);
}
}
}
field.setAccessible(fieldAccessible);
} catch (Exception e) {
e.printStackTrace();
}
}
return obj;
}
@Override
public void resolve(DeserializationContext ctxt) throws JsonMappingException {
((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
}
}发布于 2021-06-07 17:40:50
作文
首先,在这种情况下,我建议您使用组合而不是继承。您的代码将类似于下面的代码:
private class Link {
private final HrefType field;
private final HashMap<String, HrefType> test;
public Link(HrefType field) {
this.field = field;
}
public HrefType getField() {
return field;
}
public HashMap<String, HrefType> getTest() {
return test;
}
}和预期的一样,序列化也会正常工作。
串行器
但是,如果无法更改原始代码,则可以编写自己的StdSerializer。例如:
private class LinkSerializer extends StdSerializer<Link> {
public LinkSerializer() {
super(Link.class);
}
@Override
public void serialize(Link link, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
final HrefType field = link.getField();
jsonGenerator.writeObjectField("field", field);
jsonGenerator.writeObjectField("test", new HashMap<>(link));
jsonGenerator.writeEndObject();
}
}并在您的Link类上声明:
@JsonSerialize(using = LinkSerializer.class)
private static class Link extends HashMap<String, HrefType> {
private final HrefType field;
public Link(HrefType field) {
this.field = field;
}
public HrefType getField() {
return field;
}
}https://stackoverflow.com/questions/67873120
复制相似问题