Java 如何使Jackson序列化程序更加干燥?
我正在使用它作为客户端框架。开箱即用,这个框架需要某种格式的JSON。我正试图让Jackson输出这种格式。这对于回答这个问题并不重要,但提到了它并对其进行了标记,因为它可能会在相同的情况下帮助更多的用户 基本上,我希望每个被引用的对象(不是根对象)都作为它们的id输出。 这些类别:Java 如何使Jackson序列化程序更加干燥?,java,serialization,ember.js,jackson,Java,Serialization,Ember.js,Jackson,我正在使用它作为客户端框架。开箱即用,这个框架需要某种格式的JSON。我正试图让Jackson输出这种格式。这对于回答这个问题并不重要,但提到了它并对其进行了标记,因为它可能会在相同的情况下帮助更多的用户 基本上,我希望每个被引用的对象(不是根对象)都作为它们的id输出。 这些类别: public abstract class BaseEntity{ protected Long id; } public class Resource{ private String name;
public abstract class BaseEntity{
protected Long id;
}
public class Resource{
private String name;
private AnotherResource subResource;
private List<AnotherResource> subResources;
//getters and setters
}
public class SubResource{
private String value;
//getters and setters
}
我们可以注意到以下几点:
“\u id”
或“\u id”
连接,具体取决于它是引用对象还是引用对象的集合@JsonProperty
注释对其进行了分类
至于其余部分,我编写了以下序列化程序:
public class BaseEntityIdSerializer extends JsonSerializer<BaseEntity> implements ContextualSerializer {
public void serialize(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
}
@Override
public void serializeWithType(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov,
BeanProperty property) throws JsonMappingException {
if(property.getType().isCollectionLikeType()){
return new BaseEntityIdCollectionSerializer();
} else {
return new BaseEntityIdSimpleSerializer();
}
}
public class BaseEntityIdSimpleSerializer extends StdSerializer<BaseEntity>{
public BaseEntityIdSimpleSerializer(){
super(BaseEntity.class);
}
@Override
public void serialize(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeNumber(value.getId());
}
@Override
public void serializeWithType(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
}
public class BaseEntityIdCollectionSerializer extends StdSerializer<Collection<? extends BaseEntity>>{
public BaseEntityIdCollectionSerializer(){
super(Collection.class, false);
}
@Override
public void serialize(Collection<? extends BaseEntity> value,
JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException {
jgen.writeStartArray();
for(BaseEntity b:value){
jgen.writeNumber(b.getId());
}
jgen.writeEndArray();
}
@Override
public void serializeWithType(Collection<? extends BaseEntity> value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
}
}
公共类BaseEntityIdSerializer扩展JsonSerializer实现ContextualSerializer{
public void serialize(BaseEntity值,JsonGenerator jgen,
SerializerProvider提供程序)引发IOException,
JsonProcessingException{
}
@凌驾
public void serializeWithType(基本实体值,JsonGenerator jgen,
SerializerProvider提供程序,TypeSerializer(typeSer)
抛出IOException、JsonProcessingException{
序列化(值、jgen、提供程序);
}
@凌驾
公共JsonSerializer CreateContext(SerializerProvider,
BeanProperty属性)引发JsonMappingException{
if(property.getType().isCollectionLikeType()){
返回新的BaseEntityIdCollectionSerializer();
}否则{
返回新的BaseEntityIdSimpleSerializer();
}
}
公共类BaseEntityIdSimpleSerializer扩展了StdSerializer{
public BaseEntityIdSimpleSerializer(){
super(BaseEntity.class);
}
@凌驾
public void serialize(BaseEntity值,JsonGenerator jgen,
SerializerProvider提供程序)引发IOException,
JsonGenerationException{
writeNumber(value.getId());
}
@凌驾
public void serializeWithType(基本实体值,JsonGenerator jgen,
SerializerProvider提供程序,TypeSerializer(typeSer)
抛出IOException、JsonProcessingException{
序列化(值、jgen、提供程序);
}
}
公共类BaseEntityIdCollectionSerializer扩展了StdSerializer我不确定您是否真的需要定义自定义序列化程序:值序列化程序是否工作得很好?Jackson确实可以自动编写这些(并涵盖匹配的数组序列化器)。因此,对于集合案例,返回此;
应适用于上下文案例
属性重命名在值序列化程序级别不起作用,因为这是由POJO序列化程序(BeanSerializer
)完成的。也就是说,值序列化程序不会写入属性名称(对于JSON对象,必要时已调用该名称;对于JSON数组,已忽略根级别的值)。
这是设计的一部分,Jackson 1.0的不同结构可能是有意义的(使值序列化程序有2个方法;一个用于数组元素的根级别“简单”值;第二个用于“命名”属性值),但现在更改已经太晚了
但是:您可以通过以下方式在序列化程序之外处理重命名:
- 自定义
JacksonAnnotationIntrospector
,它使用类型信息修改名称——序列化或反序列化,或两者兼有(分别调用)
- 通过
BeanSerializerModifier
,在其中一个回调上以类似方式重命名属性
我不确定您是否真的需要定义自定义序列化程序:值序列化程序是否可以正常工作?Jackson确实可以自动编写这些内容(并涵盖匹配的数组序列化程序)。因此对于集合案例,返回此内容;
应该适用于上下文案例
属性重命名在值序列化程序级别不起作用,因为这是由POJO序列化程序(BeanSerializer
)完成的。也就是说,值序列化程序不会写入属性名称(对于JSON对象,必要时已调用该名称;对于JSON数组,已忽略根级别的值)。
这是设计的一部分,Jackson 1.0的不同结构可能是有意义的(使值序列化程序有2个方法;一个用于数组元素的根级别“简单”值;第二个用于“命名”属性值),但现在更改已经太晚了
但是:您可以通过以下方式在序列化程序之外处理重命名:
- 自定义
JacksonAnnotationIntrospector
,它使用类型信息修改名称——序列化或反序列化,或两者兼有(分别调用)
- 通过
BeanSerializerModifier
,在其中一个回调上以类似方式重命名属性
您所说的“值序列化程序”是什么意思?您是指@JsonValue
注释吗?我不能使用该注释,因为这会改变每次序列化类的方式。我需要仅在引用该类时使用id对其进行序列化。例如,如果该类被序列化为根类,则会进行标准序列化。通过编写自定义ser然后,我可以使用@JacksonSerialize
覆盖默认序列化。您有其他选择吗?这里的“值序列化程序”是指“处理对象数据的序列化程序”—还有“类型序列化程序”,它处理类型元数据的序列化,在某种程度上独立于值序列化。分离是为了避免深度耦合和必须为所有值类型编写自定义类型处理程序。是的,您仍然可以
{
"resource":{
"id": 1,
"name": "bla",
"sub_resource_id": 2,
"sub_resource_ids": [
1,
2,
3
]
}
}
public class BaseEntityIdSerializer extends JsonSerializer<BaseEntity> implements ContextualSerializer {
public void serialize(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
}
@Override
public void serializeWithType(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov,
BeanProperty property) throws JsonMappingException {
if(property.getType().isCollectionLikeType()){
return new BaseEntityIdCollectionSerializer();
} else {
return new BaseEntityIdSimpleSerializer();
}
}
public class BaseEntityIdSimpleSerializer extends StdSerializer<BaseEntity>{
public BaseEntityIdSimpleSerializer(){
super(BaseEntity.class);
}
@Override
public void serialize(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeNumber(value.getId());
}
@Override
public void serializeWithType(BaseEntity value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
}
public class BaseEntityIdCollectionSerializer extends StdSerializer<Collection<? extends BaseEntity>>{
public BaseEntityIdCollectionSerializer(){
super(Collection.class, false);
}
@Override
public void serialize(Collection<? extends BaseEntity> value,
JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException {
jgen.writeStartArray();
for(BaseEntity b:value){
jgen.writeNumber(b.getId());
}
jgen.writeEndArray();
}
@Override
public void serializeWithType(Collection<? extends BaseEntity> value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
serialize(value, jgen, provider);
}
}
}