我正在使用Jackson 2.22序列化一些现有对象,利用MixIn功能将实际对象与Jackson批注配置分离。
实际上,我的mixin是一个接口,该接口声明目标类的相同方法并对其进行注释,这是一个示例。
目标类别:
public class Product { // ... public String getName(); public String getDescription(); public String getPrice(); public String getFinalPrice(); public String getDiscount(); // ... }
和mixin:
public interface ProductApi { @JsonProperty public String getName(); @JsonProperty("price") public String getFinalPrice(); }
我的JSON应该具有更多信息,这些信息是根据目标类的几种方法或字段计算得出的。
杰克逊有可能吗?
我尝试在类中打开mixin并在其中添加新方法,但这没有用。
public class ProductApi { @JsonProperty public String getName(); @JsonProperty("price") public String getFinalPrice(); @JsonProperty("images") public List<String> getImages() { /* ... */ } }
我猜这是因为mixin仅提供目标类的注释,而后者是为序列化而读取的。
当然,如果我使用包含我需要的新方法的新子类更改要序列化的对象,那可以工作,但是对象来自我们的服务层,这意味着我必须重写所有这些方法。
我正在将Jackson与Jersey一起使用,所以不想将Jackson与其他库一起更改。
这是我的方法。
解决方案是为字段getter 指定一个定制的JsonSerializer实现。
首先,我改变了混入interface到class扩展实体(目标)类,所以它可以访问目标类的数据。
interface
class
public class ProductApi extends Product { @JsonProperty @Override public String getName() { return super.getName(); }; // ... }
接下来,我实现了JsonSerializer,它将创建我想要的派生属性:
JsonSerializer
public static class ImagesSerializer extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { Product p = (Product) jgen.getCurrentValue(); int num = p.getNumberOfImages(); List<String> imgs = new ArrayList<String>(num); for(int i = 0; i < num; i++) { String src = "/include/images/showImage.jsp?"+"id="+p.getId()+"&number="+i; imgs.add(src); } provider.defaultSerializeValue(imgs, jgen); } }
这是一个非常简单的实现,应该进行更多的安全检查。
基本上,这是从JSON生成器检索整个实体实例,构建一个自定义对象,然后要求Jackson对其进行序列化。 我在我内部ProductApi将其实现为静态类,但只是为了简单起见。
ProductApi
最后,序列化器需要绑定到带JsonProperty注释的字段:
JsonProperty
public class ProductApi extends Product { @JsonProperty @Override public String getName() { return super.getName(); }; // ... @JsonSerialize(using=ImagesSerializer.class) @JsonProperty("images") @Override public String getImage() { // in my entity this returns an image number, whereas in my JSON I want a list of URLs return ""; } // ... }
作为附带说明,似乎getImage()未使用该方法的返回值。
getImage()