java如何重写jackson ObjectReader?

标签 java json rest jersey jackson

我正在使用 jersey 和 jackson 编写休息服务。我有类似this example的东西

import com.mkyong.Track;

@Path("/json/metallica")
public class JSONService {

   @GET
   @Path("/get")
   @Produces(MediaType.APPLICATION_JSON)
   public Track getTrackInJSON() {

       Track track = new Track();
       track.setTitle("Enter Sandman");
       track.setSinger("Metallica");
       return track;
   }

   @POST
   @Path("/post")
   @Consumes(MediaType.APPLICATION_JSON)
   public MyResponse createTrackInJSON(Track track) {

       return new MyResponse().setResult(true);
   }
}

但就我而言,Track 类不是一个简单的 pojo bean。我使用 Map 来保存数据,并创建一个方法来从我的对象生成 json,并创建一个构造函数来解析 json 数据。

public class JsonObject {

    Map<String, String> data = new HashMap<>();

    public String toJson(){
        return "";
    }
}
public class Track extends JsonObject {

    public Track(String json) {
        //Parse json
        // [...]
    }

    public Track(JsonNode node) {
        //Parse node
        // [...]
    }


    public String getTitle() {
        if(data.containsKey("title"))
            return data.get("title");
        return "";
    }

    public void setTitle(String title) {
        data.put("title", title);
    }

    public String getSinger() {
        if(data.containsKey("singer"))
            return data.get("singer");
        return "";
    }

    public void setSinger(String singer) {
        data.put("singer", singer);
    }

    @Override
    public String toString() {
        return "Track [title=" + getTitle() + ", singer=" + getSinger() + "]";
    }

    public String toJson() {
        return "{\"title\": \"" + getTitle() + "\", \"singer\": \"" + getSinger() + "\"}";
    }
}

public class MyResponse extends JsonObject {

    public boolean getResult() {
        if(data.containsKey("result"))
            return (boolean) data.get("result");
        return false;
    }

    public MyResponse setResult(boolean value) {
        data.put("result", value);
        return this;
    }

    @Override
    public String toString() {
        return "{\"result\": " + getResult() + "}";
    }
}

所以我的问题是:是否可以在方法调用之前和之后创建操作来告诉 jackson 如何生成或解析我的对象?使用注释和/或创建 ObjectReader 或类似的东西?

谢谢

<小时/>

编辑:

谢谢皮斯基莱特。

我不确定 @JsonAnyGetter 和 @JsonAnySetter 是我的解决方案。我有许多扩展 JsonObject 的对象,我想将其与我的其余 api 的 getter 和 setter 一起保留。

所以我创建了一个通用的 JsonSerializer:

public class MyObjectSerializer extends JsonSerializer<JsonObject> {

    @Override
    public void serialize(JsonObject value, JsonGenerator gen, SerializerProvider serializers)
        throws IOException, JsonProcessingException {

        gen.writeRaw(value.toJson());
    }
}

然后我将此注释添加到 MyResponse 对象。

@JsonSerialize(using = MyObjectSerializer.class)
public class MyResponse ...

我希望我不必在每个对象中添加此注释,并且这是在休息服务返回期间自动完成的,但它工作正常并且没有那么严格。

现在我在反序列化方面遇到了另一个问题。我想要一个通用的反序列化器调用带有参数 JsonNode 的构造函数。但我怎么知道哪个类调用呢?

我在@JsonDeserialize注释中看到了一个参数“as”。

@JsonDeserialize(using = MyObjectDeserializer.class, as=Track.class)

但我没有找到如何在 JsonDeserializer 中获取此信息。任何想法 ?

(也许我可以为这个问题打开另一个线程)

最佳答案

我解决了我的问题。

对于序列化,我为我在 contextResolver 中定义的 JsonObject 创建了一个序列化器。所有扩展 JsonObject 的类都使用此序列化器进行序列化。

    public class MyJsonSerializer extends JsonSerializer<JsonObject> {

        @Override
        public void serialize(JsonObject value, JsonGenerator gen, SerializerProvider serializers)
                throws IOException, JsonProcessingException {

            gen.writeRaw(value.toJson());
        }
    }


    @Provider
    public class JacksonJsonProvider implements ContextResolver<ObjectMapper> {

        private static final ObjectMapper MAPPER = new ObjectMapper();

        static {
            MAPPER.setSerializationInclusion(Include.NON_NULL);
            MAPPER.enable(SerializationFeature.INDENT_OUTPUT);
            MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        }

        public JacksonJsonProvider() {

            SimpleModule simpleModule = new SimpleModule("SimpleModule", new Version(1,0,0,null, null, null));
            simpleModule.addSerializer(JsonObject.class, new MyJsonSerializer());
            MAPPER.registerModule(simpleModule);

        }

        @Override
        public ObjectMapper getContext(Class<?> type) {
            LOGGER.debug("JacksonProvider.getContext() called with type: "+type);
            return MAPPER;
        }
    }

对于反序列化,我使用注释@JsonCreator()来指示jackson使用什么方法来创建对象。

    @JsonCreator()
    public JsonObject(JsonNode json) {
        super(json);
    }

关于java如何重写jackson ObjectReader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34497080/

相关文章:

java - 具有初始值的 Class 实例的静态数组列表

java - 如果文件位于目录中,如何发现为什么抛出 FileNotFoundException?

java - 来自 Java 的 MySQL : Inserting a default value using a PreparedStatement INSERT query parameter

java - 如何计算 JAX-WS 中的请求处理时间?

java - 实体管理器-创建查询-嵌套选择

java - 下面是尝试通过java程序从文本文件读取的json数据。面临解析错误

json - 如何在 Node-RED 函数中解析 JSON

ruby - 试图从 ruby​​ 中解析的 JSON 中提取键值

python-2.7 - 如何在Python WebApp2中获取obj中的所有查询参数

Restful 网络服务