【问题标题】:Jackson Databind ObjectMapper convertValue with custom mapping implementaionJackson Databind ObjectMapper convertValue 与自定义映射实现
【发布时间】:2020-04-01 14:25:42
【问题描述】:

Foo1

public class Foo1{

private Long id;
private String code;
private String name;
private Boolean rState;
private String comments;     // Contain json data
private String attachments;  // Contain json data

}

Foo2

public class Foo2{

private Long id;
private String code;
private String name;
private Boolean rState;
private List comments;
private List attachments;

}

转换值

new ObjectMapper().convertValue(foo1, Foo2.class);

有没有可能,当我调用convert value时,json String会自动转换成list?

【问题讨论】:

    标签: java jackson jackson-databind


    【解决方案1】:

    我建议使用Deserializer,因为Foo1 实际上可能在其他地方被序列化,我们可能只需要转换它的序列化数据。这就是我们的目标。

    创建一个反序列化List 类型的SimpleModule

    public class ListDeserializer extends StdDeserializer<List> {
    
        public ListDeserializer() {
            super(List.class);
        }
    
        @Override
        public List deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException {
            if (p.getCurrentName().equals("result") || p.getCurrentName().equals("attachments")) {
                JsonNode node = p.getCodec().readTree(p);
                return new ObjectMapper().readValue(node.asText(), List.class);
            }
            return null;
        }
    }
    

    上面的反序列化器只识别resultattachments而忽略其余的。所以这是 Foo2 类中 List 的一个非常具体的反序列化器。

    我的测试Foo1Foo2如下

    public class Foo1 {
    
        String result = "[\"abcd\", \"xyz\"]";
    
        public String getResult() {
            return result;
        }
    
        public void setResult(String result) {
            this.result = result;
        }
    }
    
    public class Foo2 {
    
        List result;
    
        public List getResult() {
            return result;
        }
    
        public void setResult(List result) {
            this.result = result;
        }
    }
    

    我对上面的代码进行了如下测试

    // Module to help deserialize List objects
    SimpleModule listModule = new SimpleModule();
    listModule.addDeserializer(List.class, new ListDeserializer());
    
    ObjectMapper objectMapper = new ObjectMapper().registerModules(listModule);
    Foo2 foo2 = objectMapper.convertValue(new Foo1(), Foo2.class);
    System.out.println(foo2.getResult());
    

    输出是

    [abcd, xyz]
    

    【讨论】:

      【解决方案2】:

      选项 1:只注释 Foo1.class 的 getter 方法

      @JsonProperty("comments")
              public List getComments() {
                  List list = new ArrayList();
                  list.add(comments);
                  return list;
              }
      
       @JsonProperty("attachments")
              public List getAttachments() {
                  List list = new ArrayList();
                  list.add(attachments);
                  return list;
              }
      
      
      Foo1 foo1 = new Foo1(Long.valueOf(1),"a","aaa",true,"abc","def");
      System.out.println(new ObjectMapper().writeValueAsString(foo1));
      Foo2 foo2 = new ObjectMapper().convertValue(foo1, Foo2.class);
      System.out.println(new ObjectMapper().writeValueAsString(foo2));
      

      选项 2:使用 jackson-custom-serialization

      ObjectMapper mapper = new ObjectMapper();
      SimpleModule simpleModule = new SimpleModule();
      simpleModule.addSerializer(Foo1.class,new ListSerializer());
      mapper.registerModule(simpleModule);
      
      
      public class ListSerializer extends StdSerializer<Foo1> {
      
          public ListSerializer() {
              this(null);
          }
      
          protected ListSerializer(Class<Blah.Foo1> t) {
              super(t);
          }
      
          public void serialize(Blah.Foo1 foo1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
              jsonGenerator.writeStartObject();
              List list = new ArrayList();
              list.add(foo1.getComments());
      
              List list1 = new ArrayList();
              list1.add(foo1.getAttachments());
      
              jsonGenerator.writeObjectField("id",foo1.getId());
              jsonGenerator.writeObjectField("code",foo1.getCode());
              jsonGenerator.writeObjectField("name",foo1.getName());
              jsonGenerator.writeObjectField("rState",foo1.getrState());
              jsonGenerator.writeObjectField("comments",list);
              jsonGenerator.writeObjectField("attachments",list1);
              jsonGenerator.writeEndObject();
          }
      }
      
      
      Foo1 foo1 = new Foo1(Long.valueOf(1),"a","aaa",true,"abc","def");
      System.out.println(mapper.writeValueAsString(foo1));
      Foo2 foo2 = mapper.convertValue(foo1, Foo2.class);
      System.out.println(new ObjectMapper().writeValueAsString(foo2));
      

      【讨论】:

      • 我不想创建 getter 方法,因为我正在使用 lombok。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      相关资源
      最近更新 更多