【问题标题】:Jackson double serialized json string to Java object杰克逊双序列化 json 字符串到 Java 对象
【发布时间】:2016-10-28 09:29:12
【问题描述】:

我有一个 Json 字符串,它有一个字符串消息字段。 字符串:

{  "Type" : "Text",
   "Subject" : "data received",
   "Message" :"{\\"language\\":\\"US\\",\\"data\\":\\"signature\\"}"
}

我想把它转换成下面的结构: Notification.java

public class Notification {
  String type;
  String subject;
  Message message;
}

消息.java

public class Message {
  String language;
  String data;
}

有没有一种方法可以直接将字符串转换为上述结构的 Java 对象?我想避免反序列化两次。

【问题讨论】:

  • 您的问题不清楚。首先你提到了一些关于从 Object 到 String 的双重序列化然后你问关于从 String 到 Object 的反序列化
  • message字段不是json结构,是json字符串。所以我必须将它转换为一个 Notification 对象,其中字段 message 为字符串,然后将消息字符串转换为 Message 对象。
  • 现在我明白了。感谢您的澄清

标签: java json jackson


【解决方案1】:

您可以创建自定义Deserializer 以将Message 文本反序列化为Message 对象并使用@JsonDeserialize 注释Message 类:

@JsonDeserialize(using = MessageDeserializer.class)
public class Message {
    String language;
    String data;
}

public class MessageDeserializer extends JsonDeserializer<Message> {

    public MessageDeserializer() {
        super();
    }

    @Override
    public Message deserialize(
            final JsonParser jsonParser, final DeserializationContext deserializationContext) throws
            IOException, JsonProcessingException {
        final String messageText = jsonParser.getText(); 
        // parse messageText into Message object
    }
}

【讨论】:

    【解决方案2】:

    我不确定我的解决方案是否可以接受,因为它确实需要对ObjectMapper 进行额外的显式调用才能执行Message 的字符串值的反序列化。
    但是,这是在 Notification 对象的构建过程中完成的,不需要 String 消息属性。

    您需要向Message 类添加一个带有String 参数的ctor,您可以在其中将String 反序列化为Map 并提取实例属性:

    public Message(String str) {
        try {
            @SuppressWarnings("unchecked")
            Map<String, Object> map = 
                    (Map<String, Object>)new ObjectMapper().readValue(str, Map.class);
            language = map.containsKey("language") ? map.get("language").toString() : null ;
            data = map.containsKey("data") ? map.get("data").toString() : null ;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    当您反序列化 Notification 对象时,Jackson 将调用新的 ctor:

    Notification n = (Notification)new ObjectMapper().readValue(reader, Notification.class);
    

    【讨论】:

      【解决方案3】:

      您可以将 json 字符串转换为 Map 中的键值对。您必须执行两次操作,因为 Message 值又是一个 json 字符串。使用 org.json 作为 JSONObject

          Map<String, String> map = new HashMap<String, String>();
          JSONObject j = new JSONObject(str);
          Iterator<String> keys = j.keys();
      
          while( keys.hasNext() ){
              String key = (String)keys.next();
              String val = j.getString(key); 
              map.put(key, val);}
      

      然后通过遍历键检索值并将值传递给类构造函数

      然后map.get(key) 可用于检索值并将传递给类的构造函数。

      【讨论】:

        【解决方案4】:

        org.json 库易于使用:

            //Create Json object to parse string
            // str is input string
            JSONObject obj = new JSONObject(str);
        
            //Create Message
            Message mess = new Message();
            JSONObject obj2 = new JSONObject(obj.getString("Message"));
            mess.data = obj2.getString("data");
            mess.language = obj2.getString("language");
        
            //Create Notification 
            Notification noti = new Notification();
            noti.message = mess;
            noti.subject = obj.getString("Subject");
            noti.type = obj.getString("Type");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-05
          • 2017-09-22
          • 2020-10-13
          • 2016-12-07
          • 1970-01-01
          • 2020-12-12
          • 1970-01-01
          相关资源
          最近更新 更多