【问题标题】:Java & Json: Wrapping elements when serialisingJava 和 Json:序列化时包装元素
【发布时间】:2013-07-10 09:44:02
【问题描述】:

只是想知道是否有办法做到这一点 - 我有一门课,比如

class MyClass {
    private String name;
    private String address;
    private String number;
}

当我使用 Jackson 将它序列化为 Json 时,我想将 String 变量包装在一起,所以它看起来像

{
    "Strings": {
         "name" : "value",
         "address" : "value"
    }
 }

如果不将这些变量包装在 MyClass 内的 List 或 Map 类中...这可能吗?

【问题讨论】:

  • 您可以将此类字段包装在嵌入对象中,并将其称为“字符串”。但这对我来说真的很奇怪。
  • 所以你想要适合任何班级的东西?
  • 嗯,它应该只适用于一个类,我只想将所有内容组合在一起,所以字符串将被包装在“字符串”中:{},整数在“整数”中:{} 等等开,但我不能有任何数组符号或任何包围它的东西
  • 也许您还可以详细说明为什么您想这样做?客户端有什么好处?如果它是有益的,为什么不以同样的方式构建你的 POJO?

标签: java json jackson


【解决方案1】:

您还可以在 POJO 类中添加“Strings”、“Intigers”等的其他 getter。这些方法应返回 Map 作为结果。考虑下面的代码:

import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonProgram {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        MyClass myClass = new MyClass();
        myClass.setAddress("New York, Golden St. 1");
        myClass.setName("James Java");
        myClass.setNumber("444");

        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(myClass));
    }
}

class MyClass {

    private String name;
    private String address;
    private String number;

    @JsonIgnore
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @JsonIgnore
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @JsonIgnore
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @JsonProperty(value = "Strings")
    public Map<String, String> getStrings() {
        Map<String, String> map = new LinkedHashMap<String, String>();
        map.put("name", getName());
        map.put("address", getAddress());
        map.put("number", getNumber());
        return map;
    }
}

结果:

{
  "Strings" : {
    "name" : "James Java",
    "address" : "New York, Golden St. 1",
    "number" : "444"
  }
}

这可能不是您可以使用的最优雅的解决方案,但它很简单。

【讨论】:

    【解决方案2】:

    Jackson 使用您的类结构来决定 json 结构。如果您需要将类属性包装在另一个属性中,那么您需要考虑包装。如果不需要,则无需创建集合。只需将名称和地址放在不同的类中,然后根据需要为其包装器命名该类。然后在 MyClass 中添加包装类的实例。

    【讨论】:

    • 是的,我试图避免这样做,所以想知道是否有办法实现同样的事情,但要避免所有包装类 - 我试图避免 Json 周围的数组符号值也是:(
    【解决方案3】:

    我用JsonSerializer用Spring为我做这件事,很简单。

    你创建了一个扩展 JsonSerializer 的类

    喜欢这个:

     public class ServerResposeSerializer extends JsonSerializer<ServerResponse> {
    @Override
    public void serialize(ServerResponse objectWrapper, JsonGenerator generator,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        generator.writeStartObject();
        generator.writeNumberField("http_status", objectWrapper.getStatus().value());
        generator.writeStringField("message",objectWrapper.getMessage());
        generator.writeArrayFieldStart("objects");      
        List<?> objects = objectWrapper.getObjects();       
        for (Object object: objects)
        {
            generator.writeObject(object);
        }       
        generator.writeEndArray();
        generator.writeEndObject();
    }
    

    }

    注释 ServerResponse
    @JsonSerialize (using = ServerResposeSerializer.class)
    

    现在您可以格式化任何您想要生成任何类型 JSON 字符串的类

    【讨论】:

      【解决方案4】:

      一个有点老的问题,但在寻找相同问题的解决方案时,我遇到了this answer

      基本上使用writer()函数从ObjectMapper创建一个ObjectWriter,然后为映射设置rootName,即

      MyClass myclass = new MyClass()
      myclass.setName("a");
      myclass.setAddress("b");
      ObjectMapper mapper = new ObjectMapper();
      ObjectWriter writer = mapper.writer().withRootName("Strings");
      String json = writer.writeValueAsString(myclass);
      

      输出将是

      {
         "Strings": {
           "name" : "a",
           "address" : "b"
          }  
      }
      

      注意:

      ObjectMapper 是一个线程安全的,文档说它应该尽可能重用。

      【讨论】:

        【解决方案5】:
        @Configuration
        public class JacksonConfiguration {
        
            @Bean
            public ObjectMapper objectMapper() {
                ObjectMapper mapper = new ObjectMapper();
                mapper.enable(SerializationFeature.INDENT_OUTPUT);
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
                mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
                //mapper.setSerializationInclusion(Include.NON_DEFAULT);
                return mapper;
            }
        
            
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-21
          • 2017-03-05
          • 2019-12-22
          相关资源
          最近更新 更多