Java 如何序列化映射中对象值的类型属性?

Java 如何序列化映射中对象值的类型属性?,java,serialization,jackson,Java,Serialization,Jackson,我需要一些帮助。我必须获得下一个json: { "433434" : { "type" : "MULTIPLE", "value" : [ { "type" : "NUMBER", "value" : 322332 }, { "type" : "NUMBER", "value" : 322332 } ] } } 但我有一个: { "433434" : { "value" : [ {

我需要一些帮助。我必须获得下一个json:

{
  "433434" : {
    "type" : "MULTIPLE",
    "value" : [ {
      "type" : "NUMBER",
      "value" : 322332
    }, {
      "type" : "NUMBER",
      "value" : 322332
    } ]
  }
}
但我有一个:

{
  "433434" : {
    "value" : [ {
      "type" : "NUMBER",
      "value" : 322332
    }, {
      "type" : "NUMBER",
      "value" : 322332
    } ]
  }
}
我在用杰克逊。这是我的主课

package com.un1acker;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.un1acker.characteristic.AbstractCharacteristic;
import com.un1acker.characteristic.MultipleCharacteristic;
import com.un1acker.characteristic.NumCharacteristic;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);

        NumCharacteristic numCharacteristic = new NumCharacteristic();
        numCharacteristic.setValue(BigInteger.valueOf(322332L));
        List<AbstractCharacteristic<?>> list = new ArrayList<>();
        list.add(numCharacteristic);
        list.add(numCharacteristic);
        StringWriter sw = new StringWriter();
        MultipleCharacteristic multipleCharacteristic = new MultipleCharacteristic();
        multipleCharacteristic.setValue(list);
        Map<String, AbstractCharacteristic<?>> map = new HashMap<>();
        map.put("433434", multipleCharacteristic);
        mapper.writeValue(sw, map);

        System.out.println(sw.toString());
    }
}
package com.un1acker;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.SerializationFeature;
导入com.un1acker.characteristic.AbstractCharacteristic;
导入com.un1acker.characteristic.MultipleCharacteristic;
导入com.un1acker.characteristic.NumCharacteristic;
导入java.io.IOException;
导入java.io.StringWriter;
导入java.math.biginger;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
公共班机{
公共静态void main(字符串[]args)引发IOException{
ObjectMapper mapper=新的ObjectMapper();
configure(SerializationFeature.INDENT_输出,true);
NumCharacteristic NumCharacteristic=新的NumCharacteristic();
numCharacteristic.setValue(BigInteger.valueOf(322332L));
List>map=newhashmap();
map.put(“433434”,多特征);
mapper.writeValue(西南,地图);
System.out.println(sw.toString());
}
}
我有一个从抽象特征扩展而来的类多重特征和数字特征。计划我们有map>,它包含多个特性的值。 在NumberCharacteristic值的多特征集合列表中

package com.un1acker.characteristic;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type"
)
@JsonSubTypes({     @JsonSubTypes.Type(
        value = NumCharacteristic.class,
        name = "NUMBER"
), @JsonSubTypes.Type(
        value = MultipleCharacteristic.class,
        name = "MULTIPLE")})
public abstract class  AbstractCharacteristic<T>{

    private static final long serialVersionUID = -6524899961842198462L;
    private T value;

    public AbstractCharacteristic() {
    }

    public T getValue() {
        return this.value;
    }

    protected void setValue(T value) {
        this.value = value;
    }
}
package com.un1acker.characteristic;
导入com.fasterxml.jackson.annotation.JsonSubTypes;
导入com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY,
property=“type”
)
@JsonSubTypes({@JsonSubTypes.Type(
值=NumCharacteristic.class,
name=“编号”
),@JsonSubTypes.Type(
值=MultipleCharacteristic.class,
name=“MULTIPLE”)})
公共抽象类抽象特征{
私有静态最终长serialVersionUID=-652489961842198462L;
私人T值;
公共抽象特征(){
}
公共T getValue(){
返回此.value;
}
受保护的无效设置值(T值){
这个值=值;
}
}
数字特征类

package com.un1acker.characteristic;

import java.math.BigInteger;

public class NumCharacteristic extends AbstractCharacteristic<BigInteger> {
    private static final long serialVersionUID = 9220460768952701281L;

    public NumCharacteristic() {
    }
    public void setValue(BigInteger value) {
        super.setValue(value);
    }
}
package com.un1acker.characteristic;
导入java.math.biginger;
公共类NumCharacteristic扩展了AbstractCharacteristic{
私有静态最终长serialVersionUID=9220460768952701281L;
公共NumCharacteristic(){
}
public void setValue(BigInteger值){
super.setValue(值);
}
}
多特征类

package com.un1acker.characteristic;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.un1acker.MyCustomSerializer;

import java.util.List;
public class MultipleCharacteristic extends AbstractCharacteristic<List<? extends AbstractCharacteristic<?>>> {
    @Override
    public void setValue(List<? extends AbstractCharacteristic<?>> value) {
        super.setValue(value);
    }

    @Override
    @JsonSerialize(using = MyCustomSerializer.class)

    public List<? extends AbstractCharacteristic<?>> getValue() {
        return super.getValue();
    }
}
package com.un1acker.characteristic;
导入com.fasterxml.jackson.databind.annotation.JsonSerialize;
导入com.un1acker.MyCustomSerializer;
导入java.util.List;
公共类MultipleCharacteristic扩展AbstractCharacteristic>getValue(){
返回super.getValue();
}
}

我尝试使用重写方法serializeWithType为MultipleClass创建自定义序列化,但这不起作用。

这看起来可能是Jackson的错误。您的MultipleCharacteristic类型可以很好地序列化,并在单独使用时包含该类型,但当它是一个映射值时则不包含该类型,我希望其工作方式与此相同:

@Test // passes
public void serialize_multiple_characteristic() throws Exception {
    MultipleCharacteristic chr = new MultipleCharacteristic();
    chr.setValue(new ArrayList<>());
    ObjectMapper mapper = new ObjectMapper();
    assertThat(mapper.writeValueAsString(chr), equivalentTo("{ type: 'MULTIPLE', value: [] }"));
}

@Test // fails, got: {"xyzzy":{"value":[]}}
public void serialize_multiple_characteristic_in_map_value() throws Exception {
    MultipleCharacteristic chr = new MultipleCharacteristic();
    chr.setValue(new ArrayList<>());
    ObjectMapper mapper = new ObjectMapper();
    Map<String, MultipleCharacteristic> map = new HashMap<>();
    map.put("xyzzy", chr);
    assertThat(mapper.writeValueAsString(map), equivalentTo("{ 'xyzzy': { type: 'MULTIPLE', value: [] } }"));
}
@Test//通过
public void serialize_multiple_characteristic()引发异常{
多重特征chr=新的多重特征();
chr.setValue(新的ArrayList());
ObjectMapper mapper=新的ObjectMapper();
assertThat(mapper.writeValueAsString(chr),等价于(“{type:'MULTIPLE',value:[]));
}
@测试//失败,得到:{“xyzy”:{“value”:[]}
public void serialize_multiple_characteristic_in_map_value()引发异常{
多重特征chr=新的多重特征();
chr.setValue(新的ArrayList());
ObjectMapper mapper=新的ObjectMapper();
Map Map=newhashmap();
地图放置(“xyzzy”,chr);
assertThat(mapper.writeValueAsString(map),等价于(“{xyzy':{type:'MULTIPLE',value:[]}”);
}
(从内部看,BeanSerializer从来没有被TypeWrappedSerializer包裹过)

如果映射嵌入到某个对象中,这对您来说可能不是问题,因为Jackson似乎知道映射的类型参数(例如,它通常从包含的bean中获取),它似乎做了正确的事情:

@Test // passes
public void serialize_multiple_characteristic_in_map_value_using_writer() throws Exception {
    MultipleCharacteristic chr = new MultipleCharacteristic();
    chr.setValue(new ArrayList<>());
    ObjectMapper mapper = new ObjectMapper();
    Map<String, AbstractCharacteristic<?>> map = new HashMap<>();
    map.put("xyzzy", chr);
    // Hint to Jackson what types will be in the map
    TypeReference<?> mapType = new TypeReference<Map<String, AbstractCharacteristic<?>>>(){};
    assertThat(mapper.writerFor(mapType).writeValueAsString(map), equivalentTo("{ 'xyzzy': { type: 'MULTIPLE', value: [] } }"));
}
@Test//通过
public void使用\u writer()在\u map\u value\u中序列化\u多个\u特征\u引发异常{
多重特征chr=新的多重特征();
chr.setValue(新的ArrayList());
ObjectMapper mapper=新的ObjectMapper();

Map mapType=new TypeReference这对我来说很有用:为
多特征
添加自定义序列化程序:

public class MultipleCharacteristicValueSerializer extends JsonSerializer<MultipleCharacteristic> {

    @Override
    public void serialize(MultipleCharacteristic multipleCharacteristicValue, JsonGenerator jsonGenerator,SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeFieldName("value");
        jsonGenerator.writeStartArray();
        for (AbstractCharacteristic<?> characteristicValue : multipleCharacteristicValue.getValue()) {
            jsonGenerator.writeObject(characteristicValue);
        }
        jsonGenerator.writeEndArray();
    }

    @Override
    public void serializeWithType(MultipleCharacteristic value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException {
        typeSer.writeTypePrefixForObject(value, jgen);
        serialize(value, jgen, provider);
        typeSer.writeTypeSuffixForObject(value, jgen);
    }

    @Override
    public Class<MultipleCharacteristic> handledType() {
        return MultipleCharacteristic.class;
    }
}
公共类MultipleCharacteristicValueSerializer扩展JsonSerializer{
@凌驾
public void serialize(MultipleCharacteristic multipleCharacteristicValue、JsonGenerator JsonGenerator、SerializerProvider SerializerProvider)引发IOException、JsonProcessingException{
jsonGenerator.writeFieldName(“值”);
jsongGenerator.writeStartArray();
for(AbstractCharacteristicValue:multipleCharacteristicValue.getValue()){
jsonGenerator.writeObject(特征值);
}
jsonggenerator.writeEndArray();
}
@凌驾
public void serializeWithType(多特征值,JsonGenerator jgen,SerializerProvider,TypeSerializer typeSer)引发IOException,JsonProcessingException{
typeSer.writeTypePrefixForObject(值,jgen);
序列化(值、jgen、提供程序);
typeSer.writeTypeSuffixForObject(值,jgen);
}
@凌驾
公共类handledType(){
返回MultipleCharacteristic.class;
}
}

我找到了决策。我正在通过SimpleModule为MultipleCharacteristic添加自定义序列化程序,并覆盖下一个方法:serialize、serializeWithType、handledType。但是AnyWare
public class MultipleCharacteristicValueSerializer extends JsonSerializer<MultipleCharacteristic> {

    @Override
    public void serialize(MultipleCharacteristic multipleCharacteristicValue, JsonGenerator jsonGenerator,SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeFieldName("value");
        jsonGenerator.writeStartArray();
        for (AbstractCharacteristic<?> characteristicValue : multipleCharacteristicValue.getValue()) {
            jsonGenerator.writeObject(characteristicValue);
        }
        jsonGenerator.writeEndArray();
    }

    @Override
    public void serializeWithType(MultipleCharacteristic value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException {
        typeSer.writeTypePrefixForObject(value, jgen);
        serialize(value, jgen, provider);
        typeSer.writeTypeSuffixForObject(value, jgen);
    }

    @Override
    public Class<MultipleCharacteristic> handledType() {
        return MultipleCharacteristic.class;
    }
}