包含FQCN的Java Jackson序列化程序
我正在尝试创建一个通用Jackon多态序列化程序,该程序能够以这种格式(包括对象类的fqcn)序列化和反序列化JSON:包含FQCN的Java Jackson序列化程序,java,json,class,jackson,Java,Json,Class,Jackson,我正在尝试创建一个通用Jackon多态序列化程序,该程序能够以这种格式(包括对象类的fqcn)序列化和反序列化JSON: { "fqcn": "full qualified class name of the object", "data": "serialized object" } 此包装器应应用于任何对象,例如,这将是HashMap>对象的JSON表示: { "fqcn": "java.util.HashMap", "data": { "key1": {
{
"fqcn": "full qualified class name of the object",
"data": "serialized object"
}
此包装器应应用于任何对象,例如,这将是HashMap>对象的JSON表示:
{
"fqcn": "java.util.HashMap",
"data": {
"key1": {
"fqcn": "java.util.ArrayList",
"data": [
{
"fqcn": "java.lang.String",
"data": "value1"
},
{
"fqcn": "java.lang.String",
"data": "value2"
}
]
},
"key2": {
...
}
}
}
我可以使用MixIn注释将所有对象与@JsonTypeInfo
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public interface ObjMixin {
}
---
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Object.class, ObjMixin.class);
但是,格式与所需格式不匹配:{“fqcn”:…,“data”:…}
我还尝试注册StdConverter以将任何对象转换为包装器,如下所示:
public class ObjectWrapper {
private String fqcn;
private Object data;
public ObjectWrapper(Object obj) {
this.fqcn = obj.getClass.getCanonicalName();
this.data = obj;
}
}
但是,无法为对象.class
创建StdDelegatingSerializer
使用如下自定义的StdSerializer
,我得到了StackOverflowError
:
@Override
public void serialize(Object obj, JsonGenerator jsonGen, SerializerProvider serializerProvider) throws IOException {
jsonGen.writeStartObject();
jsonGen.writeStringField("fqcn", obj.getClass().getCanonicalName());
jsonGen.writeFieldName("data");
if (obj instanceof Iterable) {
jsonGen.writeStartArray();
// Recursive serialization of all elements in the iterable
jsonGen.writeEndArray();
} else if (obj instanceof Map) {
jsonGen.writeStartObject();
// Recursive serialization of all elements in the map
jsonGen.writeEndObject();
} else {
// Infinite recursion here because I'm defining this serializer for Object.class
serializerProvider.defaultSerializeValue(obj, jsonGen);
}
}
是否有人知道任何其他解决方案能够实现这一点?您可以使用自定义序列化程序和自定义序列化程序提供程序将要序列化的每个对象包装到此包装器对象中(编辑:如果不重复工作,则更新代码以不使用包装器对象,而是写入字段):
公共类FQCNTest{
@试验
public void doTest()引发JsonProcessingException{
最终ObjectMapper om=getObjectMapper();
final Object obj=getTestObject();
最后一个字符串json=om.writeValueAsString(obj);
System.out.println(json);//{“fqcn”:“java.util.HashMap”,“data”:{“k”:{“fqcn”:“java.lang.String”,“data”:“v”}
最终对象obj2=getTestValue();
最后一个字符串json2=om.writeValueAsString(obj2);
System.out.println(json2);//{“fcqn”:“java.lang.String”,“data”:“hello”}
最终对象obj3=null;
最后一个字符串json3=om.writeValueAsString(obj3);
System.out.println(json3);//null
}
私有对象映射器getObjectMapper(){
最终ObjectMapper映射器=新ObjectMapper();
最终SerializerProvider sp=mapper.getSerializerProviderInstance();
setSerializerProvider(新的CustomSerializerProvider(sp,mapper.getSerializerFactory());
返回映射器;
}
私有对象getTestObject(){
final HashMap HashMap=新HashMap();
hashMap.put(“k”、“v”);
返回hashMap;
}
私有对象getTestValue(){
回复“你好”;
}
}
类CustomSerializerProvider扩展了DefaultSerializerProvider{
私有最终序列化提供程序defaultInstance;
受保护的CustomSerializerProvider(最终SerializerProvider默认实例,最终SerializerFactory f){
super(defaultInstance,defaultInstance.getConfig(),f);
this.defaultInstance=defaultInstance;
}
@凌驾
公共可写ObjectId findObjectId(POJO的最终对象,最终对象生成器生成器类型){
返回defaultInstance.findObjectId(forPojo,generatorType);
}
@凌驾
公共JsonSerializer serializerInstance(最终带注释,最终对象serDef)引发JsonMappingException{
返回新的CustomSerializer();
}
@凌驾
公共对象includeFilterInstance(属性的最终BeanProperty定义,最终类filterClass){
试一试{
返回defaultInstance.includeFilterInstance(forProperty,filterClass);
}捕获(最终JsonMappingException e){
抛出新的运行时异常(e);
}
}
@凌驾
公共布尔includeFilterSuppressNulls(最终对象筛选器)引发JsonMappingException{
返回defaultInstance.includeFilterSuppressNulls(过滤器);
}
@凌驾
public DefaultSerializerProvider createInstance(最终SerializationConfig配置,最终SerializationFactory jsf){
归还这个;
}
@凌驾
public void序列化值(最终JsonGenerator gen,最终对象值)引发IOException{
新建CustomSerializer().serialize(值,gen,this);
}
@凌驾
public void serializeValue(最终JsonGenerator gen、最终对象值、最终JavaType rootType)引发IOException{
super.serializeValue(gen、value、rootType);
}
@凌驾
public void serializer值(最终JsonGenerator gen、最终对象值、最终JavaType根类型、最终JsonSerializer ser)引发IOException{
super.serializeValue(gen、value、rootType、ser);
}
}
类CustomSerializer扩展了StdSerializer{
受保护的CustomSerializer(){
super(Object.class);
}
@凌驾
public void serialize(最终对象值、最终JsonGenerator gen、最终SerializerProvider提供程序)引发IOException{
如果(值==null){
provider.defaultSerializeValue(值,gen);
返回;
}
最终类clazz=value.getClass();
最终JsonSerializer serForClazz=provider.findValueSerializer(clazz);
gen.writeStartObject();
gen.writeStringField(“fqcn”,clazz.getCanonicalName());
gen.writeFieldName(“数据”);
if(Iterable的值instanceof){
WriteStartaray将军();
对于(最终对象e:((可编辑)值)){
final JsonSerializer ser=new CustomSerializer();
序列序列化(e、gen、provider);
}
writeEndArray将军();
}else if(映射的值实例){
gen.writeStartObject();
//映射中所有元素的递归序列化
对于(final Map.Entry e:((Map)value.entrySet()){
final String key=e.getKey().toString();//需要更好地处理键
最终对象mapValue=e.getValue();
gen.writeFieldName(键);
final JsonSerializer ser=new CustomSerializer();
序列化(mapValue、gen、provider);
}
writeEndObject将军();
}否则{
serForClazz.serialize(值、根、提供程序);
}
writeEndO将军
public class FQCNTest {
@Test
public void doTest() throws JsonProcessingException {
final ObjectMapper om = getObjectMapper();
final Object obj = getTestObject();
final String json = om.writeValueAsString(obj);
System.out.println(json); // {"fqcn":"java.util.HashMap","data":{"k":{"fqcn":"java.lang.String","data":"v"}}}
final Object obj2 = getTestValue();
final String json2 = om.writeValueAsString(obj2);
System.out.println(json2); // {"fcqn":"java.lang.String","data":"hello"}
final Object obj3 = null;
final String json3 = om.writeValueAsString(obj3);
System.out.println(json3); // null
}
private ObjectMapper getObjectMapper() {
final ObjectMapper mapper = new ObjectMapper();
final SerializerProvider sp = mapper.getSerializerProviderInstance();
mapper.setSerializerProvider(new CustomSerializerProvider(sp, mapper.getSerializerFactory()));
return mapper;
}
private Object getTestObject() {
final HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put("k", "v");
return hashMap;
}
private Object getTestValue() {
return "hello";
}
}
class CustomSerializerProvider extends DefaultSerializerProvider {
private final SerializerProvider defaultInstance;
protected CustomSerializerProvider(final SerializerProvider defaultInstance, final SerializerFactory f) {
super(defaultInstance, defaultInstance.getConfig(), f);
this.defaultInstance = defaultInstance;
}
@Override
public WritableObjectId findObjectId(final Object forPojo, final ObjectIdGenerator<?> generatorType) {
return defaultInstance.findObjectId(forPojo, generatorType);
}
@Override
public JsonSerializer<Object> serializerInstance(final Annotated annotated, final Object serDef) throws JsonMappingException {
return new CustomSerializer();
}
@Override
public Object includeFilterInstance(final BeanPropertyDefinition forProperty, final Class<?> filterClass) {
try {
return defaultInstance.includeFilterInstance(forProperty, filterClass);
} catch (final JsonMappingException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean includeFilterSuppressNulls(final Object filter) throws JsonMappingException {
return defaultInstance.includeFilterSuppressNulls(filter);
}
@Override
public DefaultSerializerProvider createInstance(final SerializationConfig config, final SerializerFactory jsf) {
return this;
}
@Override
public void serializeValue(final JsonGenerator gen, final Object value) throws IOException {
new CustomSerializer().serialize(value, gen, this);
}
@Override
public void serializeValue(final JsonGenerator gen, final Object value, final JavaType rootType) throws IOException {
super.serializeValue(gen, value, rootType);
}
@Override
public void serializeValue(final JsonGenerator gen, final Object value, final JavaType rootType, final JsonSerializer<Object> ser) throws IOException {
super.serializeValue(gen, value, rootType, ser);
}
}
class CustomSerializer extends StdSerializer<Object> {
protected CustomSerializer() {
super(Object.class);
}
@Override
public void serialize(final Object value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
if (value == null) {
provider.defaultSerializeValue(value, gen);
return;
}
final Class<?> clazz = value.getClass();
final JsonSerializer<Object> serForClazz = provider.findValueSerializer(clazz);
gen.writeStartObject();
gen.writeStringField("fqcn", clazz.getCanonicalName());
gen.writeFieldName("data");
if (value instanceof Iterable) {
gen.writeStartArray();
for (final Object e : ((Iterable<?>) value)) {
final JsonSerializer<Object> ser = new CustomSerializer();
ser.serialize(e, gen, provider);
}
gen.writeEndArray();
} else if (value instanceof Map) {
gen.writeStartObject();
// Recursive serialization of all elements in the map
for (final Map.Entry<?, ?> e : ((Map<?, ?>) value).entrySet()) {
final String key = e.getKey().toString(); // need to handle keys better
final Object mapValue = e.getValue();
gen.writeFieldName(key);
final JsonSerializer<Object> ser = new CustomSerializer();
ser.serialize(mapValue, gen, provider);
}
gen.writeEndObject();
} else {
serForClazz.serialize(value, gen, provider);
}
gen.writeEndObject();
}
}