java - 扩展 Jackson 自定义序列化器

标签 java json jackson

鉴于 MyClass2 扩展了 MyClass1 并且只是向 MyClass1 添加了两个属性,我为这两个类编写了两个 Jackson 自定义序列化程序,如下所示:

public class MyClass1Serializer extends JsonSerializer<MyClass1> {

    @Override
    public void serialize(MyClass1 myClass1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("ApplicationName", myClass1.getApplicationName());
        jsonGenerator.writeStringField("UserName", myClass1.getUserName());
    }       
}

public class MyClass2Serializer extends JsonSerializer<MyClass2> {

    @Override
    public void serialize(MyClass2 myClass2, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("ApplicationName", myClass2.getApplicationName());       
        jsonGenerator.writeStringField("ErrorMessage", myClass2.getErrorMessage());
        jsonGenerator.writeStringField("ResultCode", myClass2.getResultCode());
        jsonGenerator.writeStringField("UserName", myClass2.getUserName());
    }       
}

效果很好,并给出以下输出:

{"ApplicationName":"FakeApp","UserName":"Joe the Schmoe"}

{"ApplicationName":"AnotherApp","ErrorMessage":"呃哦!","ResultCode":"Errrrrm,不好...","UserName":"John Doe"}

嗯,对我来说,两个序列化方法中似乎存在代码重复,我可以从第一个序列化器中子类化第二个序列化器吗?嗯嗯...

嗯,好吧,我尝试过这个:

public class MyClass1Serializer<T extends MyClass1> extends JsonSerializer<MyClass1> {

    @Override
    public void serialize(MyClass1 myClass1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("ApplicationName", myClass1.getApplicationName());
        jsonGenerator.writeStringField("UserName", myClass1.getUserName());
    }       
}

public class MyClass2Serializer extends MyClass1Serializer<MyClass2> {

    public void serialize(MyClass2 myClass2, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        super.serialize(myClass2, jsonGenerator, serializerProvider);
        jsonGenerator.writeStringField("ErrorMessage", myClass2.getErrorMessage());
        jsonGenerator.writeStringField("ResultCode", myClass2.getResultCode());
    }       
}

它编译并运行,但给我这个输出:

{"ApplicationName":"FakeApp","UserName":"Joe the Schmoe"}

{"ApplicationName":"AnotherApp","UserName":"John Doe"}

我很清楚,MyClass2Serializer 现在完全被忽略,Jackson 找到了 MyClass1Serializer 并将其用于 MyClass2。 (因为它不直接子类 JsonSerializer?)

对于这种简单的情况来说,没什么大不了的,但是我在工作中的真实类结构确实可以通过将自定义序列化器“链接”在一起而不是从头开始每个序列化器而受益。

为了以防万一,我通过类上的注释告诉 Jackson 哪个序列化器用于哪个类:

@JsonSerialize(using=MyClass1Serializer.class)
public class MyClass1 {

future 可能的问题:假设子类化自定义序列化器是可能的,子类化自定义反序列化器也可以工作吗?指向一些示例代码或教程的指针会很棒!

最佳答案

有趣的事情:我试图复制这个问题,但它似乎有效:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.*;

public class Test
{
    public static void main(String[] args) {
        MyClass1 myc1 = new MyClass1("app1", "user1");
        MyClass1 myc2 = new MyClass2("app2", "user2", "err2", "rc2");

        try {
            System.out.println(new ObjectMapper().writeValueAsString(myc1));
            System.out.println(new ObjectMapper().writeValueAsString(myc2));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @JsonSerialize(using = MyClass1Serializer.class)
    public static class MyClass1 {
        protected String applicationName;
        protected String userName;

        public MyClass1() {}

        public MyClass1(String applicationName, String userName) {
            this.applicationName = applicationName;
            this.userName = userName;
        }

        public String getApplicationName() { return applicationName; }
        public String getUserName()        { return userName; }
    }

    @JsonSerialize(using = MyClass2Serializer.class)
    public static class MyClass2 extends MyClass1 {
        protected String errorMessage;
        protected String resultCode;

        public MyClass2() {}

        public MyClass2(String applicationName, String userName, String errorMessage, String resultCode) {
            super(applicationName, userName);
            this.errorMessage = errorMessage;
            this.resultCode = resultCode;
        }

        public String getErrorMessage() { return errorMessage; }
        public String getResultCode()   { return resultCode; }
    }

    public static class MyClass1Serializer<T extends MyClass1> extends JsonSerializer<T> {
        @Override
        public void serialize(MyClass1 myClass1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException
        {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("ApplicationName", myClass1.getApplicationName());
            jsonGenerator.writeStringField("UserName", myClass1.getUserName());
            //jsonGenerator.writeEndObject();
        }
    }

    public static class MyClass2Serializer extends MyClass1Serializer<MyClass2> {
        @Override
        public void serialize(MyClass2 myClass2, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException
        {
            super.serialize(myClass2, jsonGenerator, serializerProvider);
            jsonGenerator.writeStringField("ErrorMessage", myClass2.getErrorMessage());
            jsonGenerator.writeStringField("ResultCode", myClass2.getResultCode());
            //jsonGenerator.writeEndObject();
        }
    }
}

输出:

{"ApplicationName":"app1","UserName":"user1"}
{"ApplicationName":"app2","UserName":"user2","ErrorMessage":"err2","ResultCode":"rc2"}

关于java - 扩展 Jackson 自定义序列化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33771730/

相关文章:

java - SIP Mobicents - 如何在现有对话框中创建新请求? (相同的调用 ID)

json - 如何从 MongoDB + Node.js + Mongoose 获取修改后的 json 输出

java - 使用 Java 从文本文件中读取/求和数字

json - PostgreSQL 9.3 : Adding new Fields to JSON Type

C++ REST SDK (Casablanca) web::json 迭代

java - 带有通知的未知属性失败

java - 如何从 @JsonInclude(JsonInclude.Include.NON_NULL) 中排除字段

java - Jackson JsonNode 到类型集合

java - 哪些数据库支持同步复制(Java/嵌入式首选)?

java - 在安卓游戏中放置主游戏循环的位置