Java Jackson反序列化:我可以在to反序列化对象的字段上注入一个带有注释的值吗?

Java Jackson反序列化:我可以在to反序列化对象的字段上注入一个带有注释的值吗?,java,json,jackson,deserialization,json-deserialization,Java,Json,Jackson,Deserialization,Json Deserialization,我有这样一个对象要反序列化: public class RelationsInput { Relation relation1; Relation relation2; } 而类关系如下所示: public class Relation { RelationType relationtype; ... (more fields) } public class RelationTypeJsonSerializer extends JsonSerializer&

我有这样一个对象要反序列化:

public class RelationsInput {

   Relation relation1;

   Relation relation2;

}
而类
关系
如下所示:

public class Relation {

   RelationType relationtype;
   ... (more fields)

}
public class RelationTypeJsonSerializer extends JsonSerializer<RelationType> {

    @Override
    public void serialize(RelationType value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String string = value.toString();//or something like that, convert the enum to string as you like
        gen.writeString(string);
    }
}

public class RelationTypeJsonDeserializer extends JsonDeserializer<RelationType> {

    @Override
    public RelationType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String toString = p.getCodec().readValue(p, String.class);//read the value as string
        return RelationType.build(toString);//convert back the value to object, use switch if needed)
    }
}

ObjectMapper om = new ObjectMapper();
SimpleModule localDateModule = new SimpleModule("RelationType Module");
localDateModule.addSerializer(RelationType.class, new RelationTypeJsonSerializer());
localDateModule.addDeserializer(RelationType.class, new RelationTypeJsonDeserializer());
om.registerModule(localDateModule);
Map<String, RelationType> map = new HashMap<String, RelationType>();
map.put("Some Type", RelationType.SOME_TYPE);
map.put("Some Other Type", RelationType.SOME_OTHER_TYPE);
RelationType
是enum,不是一个将被反序列化的值,而所有其他值都是

是否可以在类
RelationInput
中的字段上使用注释“注入”字段
relationType
的枚举值? 像下面这样


public class RelationsInput {

   @RelationType(RelationType.OWNER)
   Relation owner;

   @RelationType(RelationType.TENANT)
   Relation tenant;

}

杰克逊提供了这样的东西吗?

恐怕没有这样的东西。如果您想使用类似的注释,可以使用自定义反序列化程序。首先创建如下内容:

@RequiredArgsConstructor
public abstract class RelationTypeDeserializer extends JsonDeserializer<Relation> {
    private final RelationType relationType;

    @Override
    public Relation deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        Relation r = p.readValueAs(Relation.class);
        r.setRelationtype(relationType);
        return r;
    }
}

然后使用以下方法:

@Getter @Setter
public class RelationsInput {
    @JsonDeserialize(using = OwnerDeserializer.class)
    private Relation owner;
    @JsonDeserialize(using = TenantDeserializer.class)
    private Relation tenant;
}

您可以尝试使用
com.fasterxml.jackson.databind.deser.ContextualDeserializer
接口实现自定义反序列化程序。它允许使用上下文创建反序列化器实例

请参见以下示例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class JsonContextualDeserializerApp {
    public static void main(String[] args) throws IOException {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = JsonMapper.builder().build();
        RelationsInput info = mapper.readValue(jsonFile, RelationsInput.class);

        System.out.println(info.toString());
    }
}

@Data
class RelationsInput {

    @JsonDeserialize(using = RelationStdDeserializer.class)
    @RelationTypeInfo(RelationType.OWNER)
    private Relation owner;

    @JsonDeserialize(using = RelationStdDeserializer.class)
    @RelationTypeInfo(RelationType.TENANT)
    private Relation tenant;

}

@Data
class Relation {

    private int id;
    private RelationType relationtype;
}

enum RelationType {OWNER, TENANT}

@Retention(RetentionPolicy.RUNTIME)
@interface RelationTypeInfo {
    RelationType value();
}

class RelationStdDeserializer extends StdDeserializer<Relation> implements ContextualDeserializer {

    private RelationType propertyRelationType;

    public RelationStdDeserializer() {
        this(null);
    }

    public RelationStdDeserializer(RelationType relationType) {
        super(Relation.class);
        this.propertyRelationType = relationType;
    }

    @Override
    public Relation deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonDeserializer<Object> deser = ctxt.findRootValueDeserializer(ctxt.getTypeFactory().constructType(Relation.class));
        Relation instance = (Relation) deser.deserialize(p, ctxt);
        if (this.propertyRelationType != null) {
            instance.setRelationtype(this.propertyRelationType);
        }
        return instance;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
        RelationTypeInfo typeInfo = property.getMember().getAllAnnotations().get(RelationTypeInfo.class);

        return new RelationStdDeserializer(typeInfo.value());
    }
}
印刷品:

RelationsInput(owner=Relation(id=1, relationtype=OWNER), tenant=Relation(id=2, relationtype=TENANT))
另见:


如果您按照要求执行操作,RelationType字段的值将始终相同。无论如何,一个可行的解决方案是使用个性化序列化程序反序列化程序,如下所示:

public class Relation {

   RelationType relationtype;
   ... (more fields)

}
public class RelationTypeJsonSerializer extends JsonSerializer<RelationType> {

    @Override
    public void serialize(RelationType value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String string = value.toString();//or something like that, convert the enum to string as you like
        gen.writeString(string);
    }
}

public class RelationTypeJsonDeserializer extends JsonDeserializer<RelationType> {

    @Override
    public RelationType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String toString = p.getCodec().readValue(p, String.class);//read the value as string
        return RelationType.build(toString);//convert back the value to object, use switch if needed)
    }
}

ObjectMapper om = new ObjectMapper();
SimpleModule localDateModule = new SimpleModule("RelationType Module");
localDateModule.addSerializer(RelationType.class, new RelationTypeJsonSerializer());
localDateModule.addDeserializer(RelationType.class, new RelationTypeJsonDeserializer());
om.registerModule(localDateModule);
Map<String, RelationType> map = new HashMap<String, RelationType>();
map.put("Some Type", RelationType.SOME_TYPE);
map.put("Some Other Type", RelationType.SOME_OTHER_TYPE);
公共类关系类型JsonSerializer扩展JsonSerializer{
@凌驾
public void serialize(RelationType值、JsonGenerator gen、SerializerProvider序列化程序)引发IOException{
String String=value.toString();//或类似的内容,根据需要将枚举转换为字符串
gen.writeString(字符串);
}
}
公共类RelationTypeJsonDeserializer扩展JsonDeserializer{
@凌驾
public RelationType反序列化(JsonParser p,DeserializationContext ctxt)引发IOException{
String-toString=p.getCodec().readValue(p,String.class);//将值作为字符串读取
返回RelationType.build(toString);//将值转换回object,如果需要,使用switch)
}
}
ObjectMapper om=新的ObjectMapper();
SimpleModule localDateModule=新的SimpleModule(“RelationType模块”);
addSerializer(RelationType.class,新的RelationTypeJsonSerializer());
addDeserializer(RelationType.class,新的RelationTypeJsonDeserializer());
注册表模块(localDateModule);
要前后转换枚举,我建议使用map、super simple和work perfect,如下所示:

public class Relation {

   RelationType relationtype;
   ... (more fields)

}
public class RelationTypeJsonSerializer extends JsonSerializer<RelationType> {

    @Override
    public void serialize(RelationType value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String string = value.toString();//or something like that, convert the enum to string as you like
        gen.writeString(string);
    }
}

public class RelationTypeJsonDeserializer extends JsonDeserializer<RelationType> {

    @Override
    public RelationType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String toString = p.getCodec().readValue(p, String.class);//read the value as string
        return RelationType.build(toString);//convert back the value to object, use switch if needed)
    }
}

ObjectMapper om = new ObjectMapper();
SimpleModule localDateModule = new SimpleModule("RelationType Module");
localDateModule.addSerializer(RelationType.class, new RelationTypeJsonSerializer());
localDateModule.addDeserializer(RelationType.class, new RelationTypeJsonDeserializer());
om.registerModule(localDateModule);
Map<String, RelationType> map = new HashMap<String, RelationType>();
map.put("Some Type", RelationType.SOME_TYPE);
map.put("Some Other Type", RelationType.SOME_OTHER_TYPE);
Map Map=newhashmap();
map.put(“Some Type”,RelationType.Some_Type);
map.put(“其他类型”,RelationType.Some\u其他类型);
并使用get(字符串)进行序列化 和get(value)进行反序列化(查找某个值的键) 这是一个常规示例,当您想要序列化没有默认序列化程序反序列化程序的内容时 更多信息请看这个

为什么不序列化/反序列化relationType字段?这可能有助于更好地理解枚举和序列化,因为序列化数据中不包含字段。它是
RelationsInput
类的上下文信息。