您的大部分(全部?)要求都可以通过使用上下文序列化程序来实现。通过ContextualDeserializer的一个答案,使用Jackson和Jackson的Wiki(http://wiki.fasterxml.com/JacksonFeatureContextualHandlers)将JSON映射到不同类型的地图,我能够提出以下内容。
您需要从@JsonId批注开始,这是指示属性仅需要使用Id属性的键。
import com.fasterxml.jackson.annotation.*;import java.lang.annotation.*;@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotation // important so that it will get included!public @interface JsonId {}
接下来是实际的ContextualSerializer,它完成了繁重的工作。
import com.fasterxml.jackson.databind.ser.*;import com.fasterxml.jackson.databind.*;import com.fasterxml.jackson.core.*;import java.io.*;public class ContextualJsonIdSerializer extends JsonSerializer<baseResource> implements ContextualSerializer{ private ObjectMapper mapper; private boolean useJsonId; public ContextualJsonIdSerializer(ObjectMapper mapper) { this(mapper, false); } public ContextualJsonIdSerializer(ObjectMapper mapper, boolean useJsonId) { this.mapper = mapper; this.useJsonId = useJsonId; } @Override public void serialize(baseResource br, JsonGenerator jgen, SerializerProvider provider) throws IOException { if ( useJsonId ) { jgen.writeString(br.getId().toString()); } else { mapper.writevalue(jgen, br); } } @Override public JsonSerializer<baseResource> createContextual(SerializerProvider config, BeanProperty property) throws JsonMappingException { // First find annotation used for getter or field: System.out.println("Finding annotations for "+property); if ( null == property ) { return new ContextualJsonIdSerializer(mapper, false); } JsonId ann = property.getAnnotation(JsonId.class); if (ann == null) { // but if missing, default one from class ann = property.getContextAnnotation(JsonId.class); } if (ann == null ) {//|| ann.length() == 0) { return this;//new ContextualJsonIdSerializer(false); } return new ContextualJsonIdSerializer(mapper, true); }}
此类查看
baseResource属性并检查它们以查看是否
@JsonId存在注释。如果是,则仅使用Id属性,否则将使用传入
ObjectMapper来序列化该值。这很重要,因为如果您尝试使用(基本上)在上下文中的映射器,
ContextualSerializer则将导致堆栈溢出,因为它最终将一遍又一遍地调用这些方法。
您的资源看起来应该如下所示。我使用
@JsonProperty注解而不是在中包装功能,
ContextualSerializer因为重新发明轮子似乎很愚蠢。
import java.util.*;import com.fasterxml.jackson.annotation.*;public class Resource extends baseResource{ private String name; @JsonProperty("sub_resource_id") @JsonId private SubResource subResource; @JsonProperty("sub_resource_ids") @JsonId private List<SubResource> subResources; //getters and setters public String getName() {return name;} public void setName(String name) {this.name = name;} public SubResource getSubResource() {return subResource;} public void setSubResource(SubResource subResource) {this.subResource = subResource;} public List<SubResource> getSubResources() {return subResources;} public void setSubResources(List<SubResource> subResources) {this.subResources = subResources;}}
最后,执行序列化的方法只是创建一个附加对象,
ObjectMapper并在原始对象中注册一个模块
ObjectMapper。
// Create the original ObjectMapperObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);// Create a clone of the original ObjectMapperObjectMapper objectMapper2 = new ObjectMapper();objectMapper2.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);objectMapper2.configure(SerializationFeature.WRAP_ROOT_VALUE, true);objectMapper2.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);// Create a module that references the Contextual SerializerSimpleModule module = new SimpleModule("JsonId", new Version(1, 0, 0, null));// All references to SubResource should be run through this serializermodule.addSerializer(SubResource.class, new ContextualJsonIdSerializer(objectMapper2));objectMapper.registerModule(module);// Now just use the original objectMapper to serialize
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)