mig*_*ain 9 java json jackson ember.js ember-data
我需要以特定方式配置Jackson,我将在下面介绍.
id
id
"_id"
后缀添加到属性名称"_ids"
后缀添加到属性名称@JsonId
,最好有一个可选的值来覆盖名字就像@JsonProperty
做@JsonIdentityInfo
id
属性可发现性的注释(例如,对JPA场景有用)考虑到这些POJO:
//Inform Jackson which property is the id
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id"
)
public abstract class BaseResource{
protected Long id;
//getters and setters
}
public class Resource extends BaseResource{
private String name;
@JsonId
private SubResource subResource;
@JsonId
private List<SubResource> subResources;
//getters and setters
}
public class SubResource extends BaseResource{
private String value;
//getters and setters
}
Run Code Online (Sandbox Code Playgroud)
Resource
实例的可能序列化可以是:
{
"resource":{
"id": 1,
"name": "bla",
"sub_resource_id": 2,
"sub_resource_ids": [
1,
2,
3
]
}
}
Run Code Online (Sandbox Code Playgroud)
要求#5可以通过ObjectMapper
以下方式配置来完成:
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
Run Code Online (Sandbox Code Playgroud)
然后@JsonRootName("example_root_name_here")
在我的POJO中使用.
要求#6可以通过ObjectMapper
以下方式配置来完成:
objectMapper.setPropertyNamingStrategy(
PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
Run Code Online (Sandbox Code Playgroud)如您所见,仍有许多要求需要实现.对于那些想知道为什么我需要这样的配置的人来说,这是因为我正在为ember.js(更具体地说是Ember Data)开发一个REST web服务.如果您可以帮助满足任何要求,您将非常感激.
谢谢!
大多数(全部?)您的要求可以通过使用上下文序列化器来完成.从ContextualDeserializer获得一个答案,用于将JSON映射到Jackson和Jackson的wiki(http://wiki.fasterxml.com/JacksonFeatureContextualHandlers)的不同类型的地图,我能够得到以下内容.
您需要从@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 {
}
Run Code Online (Sandbox Code Playgroud)
接下来是实际的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/*<BaseResource>*/
{
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);
}
}
Run Code Online (Sandbox Code Playgroud)
此类查看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;}
}
Run Code Online (Sandbox Code Playgroud)
最后,执行序列化的方法只会创建一个额外的ObjectMapper
并在原始模块中注册一个模块ObjectMapper
.
// Create the original ObjectMapper
ObjectMapper 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 ObjectMapper
ObjectMapper 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 Serializer
SimpleModule module = new SimpleModule("JsonId", new Version(1, 0, 0, null));
// All references to SubResource should be run through this serializer
module.addSerializer(SubResource.class, new ContextualJsonIdSerializer(objectMapper2));
objectMapper.registerModule(module);
// Now just use the original objectMapper to serialize
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6870 次 |
最近记录: |