复杂JSON字符串转换为Java嵌套对象的实现

目录
  • 背景
  • 方法
    • 预备工作
    • 构建对象模型
    • 使用jackson 库解析
    • 使用GSON解析
    • 不含列表的嵌套对象

背景

实际开发中,常常需要将比较复杂的 JSON 字符串转换为对应的 Java 对象。这里记录下解决方案。

如下所示,是入侵事件检测得到的 JSON 串:

[{"rule_id":"反弹shell","format_output":"进程 pname 反向连接到 %dest_ip%:%dest_port%","info":{"process_events":{"pid":21,"pname":"nginx","cmdline":"curl www.cfda.com","ppid":7,"ppname":"bash"},"proc_trees":[{"pid":21,"pname":"nginx","cmdline":"curl www.cfda.com","ppid":7,"ppname":"bash"}],"containers":{"container_id":"fef4636d8403871c2e56e06e51d609554564adbbf8284dd914a0f61130558bdf","container_name":"nginx","image_id":"4eb8f7c43909449dbad801c50d9dccc7dc86631e54f28b1a4b13575729065be8","status":"Running"},"sockets":{"src_ip":"127.0.0.1","src_port":"8080","type":"1","in_out":"0","dest_ip":"localhost","dest_port":"80"}}}]

方法

预备工作

把上述 json 串放在 src/test/resources 下,写一个文件读写程序来解析。 其实放在哪里不重要,重要的是拿到这个 JSON 串便于后续解析。

public static String readFromSource(String filename) {
    try {
      InputStream is = RWTool.class.getResourceAsStream(filename);
      byte[] bytes = new byte[4096];
      int num = 0;
      String json = "";
      while((num=is.read(bytes))>0){
        json=new String(bytes,0,num);
      }
      return json;
    } catch (Exception ex) {
      throw new RuntimeException(ex.getCause());
    }
}

构建对象模型

首先,要根据这个 JSON 字符串解析出对应的数据模型 AgentDetectEventData。主要就是按照 JSON 串中的 key 的层次结构来建立。

@Getter
@Setter
public class AgentDetectEventData {
    @SerializedName("rule_id")
    @JsonProperty("rule_id")
    private String ruleId;
    @SerializedName("format_output")
    @JsonProperty("format_output")
    private String formatOutput;
    @SerializedName("info")
    @JsonProperty("info")
    private AgentDetectEventDetail info;
}
@Getter
@Setter
public class AgentDetectEventDetail {
    @SerializedName("process_events")
    @JsonProperty("process_events")
    private ProcessEvent processEvent;
    @SerializedName("proc_trees")
    @JsonProperty("proc_trees")
    private List<ProcessTree> procTree;
    @SerializedName("containers")
    @JsonProperty("containers")
    private Container container;
    @SerializedName("sockets")
    @JsonProperty("sockets")
    private Socket socket;
}
@Getter
@Setter
public class ProcessEvent {
    @SerializedName("pid")
    @JsonProperty("pid")
    private String pid;
    @SerializedName("pname")
    @JsonProperty("pname")
    private String pname;
    @SerializedName("cmdline")
    @JsonProperty("cmdline")
    private String cmdline;
    @SerializedName("ppid")
    @JsonProperty("ppid")
    private String ppid;
    @SerializedName("ppname")
    @JsonProperty("ppname")
    private String ppname;
}
@Getter
@Setter
public class ProcessTree {
    @SerializedName("pid")
    @JsonProperty("pid")
    private String pid;
    @SerializedName("pname")
    @JsonProperty("pname")
    private String pname;
    @SerializedName("cmdline")
    @JsonProperty("cmdline")
    private String cmdline;
    @SerializedName("ppid")
    @JsonProperty("ppid")
    private String ppid;
    @SerializedName("ppname")
    @JsonProperty("ppname")
    private String ppname;
}
@Getter
@Setter
public class Container {
    @SerializedName("container_id")
    @JsonProperty("container_id")
    private String containerId;
    @SerializedName("container_name")
    @JsonProperty("container_name")
    private String containerName;
    @SerializedName("image_id")
    @JsonProperty("image_id")
    private String imageId;
    @SerializedName("status")
    @JsonProperty("status")
    private String status;
}
@Getter
@Setter
public class Socket {
    @SerializedName("src_ip")
    @JsonProperty("src_ip")
    private String srcIp;
    @SerializedName("src_port")
    @JsonProperty("src_port")
    private String srcPort;
    @SerializedName("type")
    @JsonProperty("type")
    private String type;
    @SerializedName("in_out")
    @JsonProperty("in_out")
    private String inOut;
    @SerializedName("dest_ip")
    @JsonProperty("dest_ip")
    private String destIp;
    @SerializedName("dest_port")
    @JsonProperty("dest_port")
    private String destPort;
}

这里有两个注意点:

  • JSON 字符串的字段命名是下划线形式,而 Java 对象的属性命名是驼峰式的,这里需要做一个字段名映射转换。 使用 Jackson 库来转换,是 @JsonProperty 注解; 使用 gson 库来转换,是 @SerializedName 注解。
  • 需要加 getter / setter 方法。

对象模型建立后,就成功了一大半。接下来,就是使用 json 库来解析了。

使用jackson 库解析

public class JsonUtil {
  private static Logger logger = LoggerFactory.getLogger(JsonUtil.class);
  private static final ObjectMapper MAPPER = new ObjectMapper();
  static {
    // 为保持对象版本兼容性,忽略未知的属性
    MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // 序列化的时候,跳过null值
    MAPPER.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
    // date类型转化
    SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    MAPPER.setDateFormat(fmt);
  }
  /**
   * 将一个json字符串解码为java对象
   *
   * 注意:如果传入的字符串为null,那么返回的对象也为null
   *
   * @param json json字符串
   * @param cls  对象类型
   * @return 解析后的java对象
   * @throws RuntimeException 若解析json过程中发生了异常
   */
  public static <T> T toObject(String json, Class<T> cls) {
    if (json == null) {
      return null;
    }
    try {
      return MAPPER.readValue(json, cls);
    } catch (Exception e) {
      throw new RuntimeException(e.getCause());
    }
  }
  public static <T> String objectToJson(T obj){
    if(obj == null){
      return null;
    }
    try {
      return obj instanceof String ? (String) obj : MAPPER.writeValueAsString(obj);
    } catch (Exception e) {
      return null;
    }
  }
  public static <T> T jsonToObject(String src, TypeReference<T> typeReference){
    if(StringUtils.isEmpty(src) || typeReference == null){
      return null;
    }
    try {
      return (T)(typeReference.getType().equals(String.class) ? src : MAPPER.readValue(src, typeReference));
    } catch (Exception e) {
      logger.warn("Parse Json to Object error",e);
      throw new RuntimeException(e.getCause());
    }
  }
  public static <T> T jsonToObject(String src, Class<?> collectionClass,Class<?>... elementClasses){
    JavaType javaType = MAPPER.getTypeFactory().constructParametricType(collectionClass,elementClasses);
    try {
      return MAPPER.readValue(src, javaType);
    } catch (Exception e) {
      logger.warn("Parse Json to Object error",e);
      throw new RuntimeException(e.getCause());
    }
  }
}

单测:

public class JsonUtilTest {
    @Test
    public void testParseJson() {
        String json = RWTool.readFromSource("/json.txt");
        List<AgentDetectEventData> ade = JsonUtil.jsonToObject(json, new TypeReference<List<AgentDetectEventData>>() {});
        Assert.assertNotNull(ade);
    }
    @Test
    public void testParseJson2() {
        String json = RWTool.readFromSource("/json.txt");
        List<AgentDetectEventData> ade = JsonUtil.jsonToObject(json, List.class, AgentDetectEventData.class);
        Assert.assertNotNull(ade);
    }
}

引入POM依赖为:

<dependency>
       <groupId>org.codehaus.jackson</groupId>
       <artifactId>jackson-mapper-asl</artifactId>
       <version>1.9.4</version>
</dependency>

使用GSON解析

public class GsonUtil {
  static GsonBuilder gsonBuilder = null;
  static {
    gsonBuilder = new GsonBuilder();
    gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss");
  }
  public static Gson getGson() {
    return gsonBuilder.create();
  }
  public static <T> T fromJson(String json, Class<T> cls) {
    return getGson().fromJson(json, cls);
  }
  public static <T> T fromJson(String json, Type type) {
    return getGson().fromJson(json, type);
  }
}

单测:

public class GsonUtilTest {
    @Test
    public void testParseJson() {
        String json = RWTool.readFromSource("/json.txt");
        List<AgentDetectEventData> ade = GsonUtil.fromJson(json, new TypeToken<List<AgentDetectEventData>>(){}.getType());
        Assert.assertNotNull(ade);
    }
}

引入 POM 为:

<dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
       <version>2.3.1</version>
</dependency>

不含列表的嵌套对象

如果是不含列表的嵌套对象,则使用带 Class cls 入参的方法:

@Test
public void testParseSimpleNestedJson() {
    String json = "{\"goods\":{\"desc\":\"2箱*250g\",\"goodsId\":8866,\"orderNo\":\"E20210522120237009258\",\"shopId\":659494,\"title\":\"认养一头牛\"},\"order\":{\"bookTime\":1621656157,\"codPay\":false,\"deliveryType\":\"express\",\"orderNo\":\"E20210522120237009258\",\"shopId\":659494,\"userId\":1476}}";
    BookInfo bookInfo = JsonUtil.toObject(json, BookInfo.class);
    Assert.assertNotNull(bookInfo);
}
@Test
public void testParseSimpleNestedJson() {
    String json = "{\"goods\":{\"desc\":\"2箱*250g\",\"goodsId\":8866,\"orderNo\":\"E20210522120237009258\",\"shopId\":659494,\"title\":\"认养一头牛\"},\"order\":{\"bookTime\":1621656157,\"codPay\":false,\"deliveryType\":\"express\",\"orderNo\":\"E20210522120237009258\",\"shopId\":659494,\"userId\":1476}}";
    BookInfo bookInfo = GsonUtil.fromJson(json, BookInfo.class);
    Assert.assertNotNull(bookInfo);
}

读者可以自行解析出 BookInfo 的对象模型。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 使用Java进行Json数据的解析(对象数组的相互嵌套)

    这段时间我们在做一个英语翻译软件的小小小APP,涉及到了对Json数据的解析,所以特地来总结一下! 假设我们要对如下数据进行解析,其实在平时,返回的Json数据是很乱的,很难分清数据的关系,这是经过相关工具美化后的结果 { "translation": [ "爱" ], "basic": { "us-phonetic": "lʌv", "phonetic": "lʌv"

  • java对象与json对象间的相互转换的方法

    工程中所需的jar包,因为在网上不太好找,所以我将它放到我的网盘里了,如有需要随便下载. 点击下载 1.简单的解析json字符串 首先将json字符串转换为json对象,然后再解析json对象,过程如下. JSONObject jsonObject = JSONObject.fromObject(jsonStr); 根据json中的键得到它的值 String name = jsonObject.getString("name"); int num = jsonObject.getInt

  • Java实现Json字符串与Object对象相互转换的方式总结

    本文实例总结了Java实现Json字符串与Object对象相互转换的方式.分享给大家供大家参考,具体如下: Json-Lib.Org.Json.Jackson.Gson.FastJson五种方式转换json类型 只列举了最省事的方式.不涉及复制情况和速度. 测试用例,一个User类,属性name,age,location.重写toString(). public class User { private String name; private Integer age; private Stri

  • Java中Json字符串直接转换为对象的方法(包括多层List集合)

    使用到的类:net.sf.json.JSONObject 使用JSON时,除了要导入JSON网站上面下载的json-lib-2.2-jdk15.jar包之外,还必须有其它几个依赖包:commons-beanutils.jar,commons-httpclient.jar,commons-lang.jar,ezmorph.jar,morph-1.0.1.jar 下面是例子代码: // JSON转换 JSONObject jsonObj = JSONObject.fromObject(jsonStr

  • 复杂JSON字符串转换为Java嵌套对象的实现

    目录 背景 方法 预备工作 构建对象模型 使用jackson 库解析 使用GSON解析 不含列表的嵌套对象 背景 实际开发中,常常需要将比较复杂的 JSON 字符串转换为对应的 Java 对象.这里记录下解决方案. 如下所示,是入侵事件检测得到的 JSON 串: [{"rule_id":"反弹shell","format_output":"进程 pname 反向连接到 %dest_ip%:%dest_port%","

  • js 将json字符串转换为json对象的方法解析

    例如: JSON字符串: var str1 = '{ "name": "cxh", "sex": "man" }'; JSON对象: var str2 = { "name": "cxh", "sex": "man" }; 一.JSON字符串转换为JSON对象 要使用上面的str1,必须使用下面的方法先转化为JSON对象: //由JSON字符串转换为

  • Java中JSON字符串与java对象的互换实例详解

    在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好,下面先看下JSON的格式, JSON可以有两种格式,一种是对象格式的,另一种是数组对象, {"name":"JSON","address":"北京市西城区","age":25}//JSON的对象格式的字符串 [

  • 将JSON字符串转换成Map对象的方法

    页面向后台action传递一个json字符串,需要将json字符串转换成Map对象 public Map<String, String> toMap(Object object) { Map<String, String> data = new HashMap<String, String>(); // 将json字符串转换成jsonObject JSONObject jsonObject = JSONObject.fromObject(object); Iterato

  • 详解json string转换为java bean及实例代码

    详解json string转换为java bean及实例代码 pom中添加如下两个库: <dependency> <groupId>org.codehaus.jackson </groupId> <artifactId>jackson-core-asl</artifactId> <version>1.9.2</version> <scope>provided</scope> </depende

  • Json字符串转换为JS对象的高效方法实例

    今天学习JQuery源码看到一下方法,原来还可以这样解析JSON字符串: 复制代码 代码如下: parseJSON: function( data ) {  if ( typeof data !== "string" || !data ) {   return null;  } // Make sure leading/trailing whitespace is removed (IE can't handle it)  data = jQuery.trim( data ); //

  • jQuery.parseJSON(json)将JSON字符串转换成js对象

    概述 接受一个JSON字符串,返回解析后的对象. 传入一个畸形的JSON字符串会抛出一个异常.比如下面的都是畸形的JSON字符串: {test: 1} ( test 没有包围双引号) {'test': 1} (使用了单引号而不是双引号) 另外,如果你什么都不传入,或者一个空字符串.null或undefined,parseJSON都会返回 null . 参数 jsonString 要解析的JSON字符串 示例 描述: 解析一个JSON字符串 jQuery 代码: var str = '{"name

  • Json字符串转Java对象和List代码实例

    对象POJO和JSON互转 public class JsonUtil { /** * JSON 转 POJO */ public static <T> T getObject(String pojo, Class<T> tclass) { try { return JSONObject.parseObject(pojo, tclass); } catch (Exception e) { log.error(tclass + "转 JSON 失败"); } re

  • java解析多层嵌套json字符串问题

    目录 java分别解析下面两个json字符串 嵌套(任意层)JSON解析转换为Map 源代码 java分别解析下面两个json字符串 package jansonDemo; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; public class TestJSON { /** * JSON实际上也是键值对("key&qu

  • 使用Jackson-json解析一个嵌套的json字符串

    目录 Jackson-json解析一个嵌套的json字符串 关于这个jar包 然后读入我的json字符串(str) 把节点展开 取到shops时就简单了,贴上代码 java解析多层嵌套json字符串 Jackson-json解析一个嵌套的json字符串 最近想尝试一下java的爬虫的编写,于是不可避免的遇到了要处理json数据的问题,于是乎用到了Jackson-json这个jar包 关于这个jar包 先在工程中导入这个jar包,然后创建一个ObjectMapper对象 ObjectMapper

随机推荐