在我使用Spring的Web应用程序中,我们希望使用自定义JSON结构。 Spring默认采用这样的POJO:
public class Model {
private int id;
private String name;
public Model(){}
public Model(int id, String name){
this.id = id;
this.name = name;
}
}
并将其变为:
{"id":1, "name":"Bob"}
通过我们的应用程序,我们希望将其转换为:
[1, "Bob"]
我想使用Spring的默认序列化逻辑来检测Java类型(int,String,Collection等)并映射到适当的JSON类型,但只需将包装对象更改为数组而不是和带有字段的对象。
这是我到目前为止的串行器(它将在带有@JsonSerialize的模型中实现(使用= Serializer.class)),但是不希望重写Spring已经实现的所有逻辑。
public class Serializer extends JsonSerializer<Model> {
@Override
public void serialize(Model value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartArray();
jgen.writeString(value.id);
.... other values ...
jgen.writeEndArray();
}
}
如何挂钩预先存在的Serializer,以便这个新的序列化程序可以像任何POJO一样工作(不仅仅是Model类,而是我们需要序列化到数组的任何类似或子类)?这可能具有混合属性,并且没有特定的属性命名约定。
我想避免为每个不同的Model类(其他值......)部分编写自定义序列化程序。
答案 0 :(得分:0)
您可以使用@JsonValue
注释。
例如:
public class Model {
private int id;
public Model(){}
public Model(int id){
this.id = id;
}
@JsonValue
public int[] getValue() {
return new int[]{this.id};
}
}
答案 1 :(得分:0)
请注意Apache BeanUtils library,尤其要注意BeanUtils.populate()
方法。
该方法的作用是根据JavaBeans约定将任何给定的Object
转换为Map<String, Object>
。在键中,您具有属性名称,而在值中,您拥有每个属性的值。对于标准情况,该方法应该足够了。请仔细阅读文档,以了解如何处理特殊情况。
Model model = ...; // get your model from some place
Map<String, Object> properties = new HashMap<>();
BeanUtils.populate(model, properties);
// Exception handling and special cases left as an excercise
以上递归填充了properties
地图,这意味着如果您的Model
有一个名为otherModel
的属性,其类型为OtherModel
,那么properties
地图将在条目中具有与otherModel
键匹配的另一个映射,以此类推其他嵌套POJO。
获得properties
地图后,您想要序列化的数组元素将在其值中。所以,像这样的事情应该做的工作:
public List<Object> toArray(Map<String, Object> properties) {
List<Object> result = new ArrayList<>();
for (Object obj : properties.values()) {
Object elem = null;
if (obj != null) {
Class<?> clz = obj.getClass();
if (Map.class.isAssignableFrom(clz)) {
elem = toArray((Map<String, Object>) obj); // recursion!
} else {
elem = obj;
}
}
result.add(elem); // this adds null values
// move 1 line up if you don't
// want to serialize nulls
}
return result;
}
然后,在调用toArray()
方法之后,您已准备好List<Object>
使用标准Spring机制进行序列化。我甚至认为你不需要特定的序列化器:
List<Object> array = toArray(properties);
return array; // return this array, i.e. from a Controller
免责声明:
请将此作为指南使用,而不是最终解决方案。我尽量小心,但代码可能有错误。我非常确定它需要对数组和Iterable
个POJO进行特殊处理。毫无疑问,它缺乏异常处理。它仅适用于POJO。如果提供的对象具有循环引用,则可能会爆炸。它没有经过测试!