一种Java编解码复杂JSON对象的简便方法

背景

前后台交换消息的格式选择JSON时,根据消息的复杂度,JSON数据的复杂度也高低不一。简单的JSON可以直接用官方json库编解码,例如

{
    "type": "response",      // package类型
    "command": "/api/move",  // 源指令
    "error_message": "",     // 错误消息
    "status": "OK",          // 执行结果
    "uuid": "123456"         // 用户定义的uuid
}

但复杂的用它就很繁琐了,例如

{
    "command": "/api/markers/query_list",
    "error_message": "",
    "status": "OK",
    "type": "response",
    "uuid": "",
    "results": {
        "1": {
            "avatar": "默认",
            "floor": 11,
            "key": 0,
            "marker_name": "1",
            "pose": {
                "orientation": {
                    "w": -1,
                    "x": 0,
                    "y": 0,
                    "z": 0.02
                },
                "position": {
                    "x": -0.72,
                    "y": -0.35,
                    "z": 0
                }
            }
        }
    }
}

这时官方json库那种一个字段一个字段地处理方式,就太繁琐了。
有没有一种方法,可以定义好数据结构,然后直接通过序列化(就是将对象编码成json串)、反序列化(就是从json串里解码出对象)技术自动编解码JSON呢?

解决方案gson

可以用Google出的gson库,它能将Java对象直接序列化成JSON串,或者将JSON串直接反序列化成一个Java对象,比起官方json库,在处理复杂json数据时的效率高了很多。

创建Util工具类

我们将gson提供的序列化、反序列化方法,都封装到一个工具类里,这样其他地方就能直接拿来用了

package com.lanplus.lanova.chassis_control.utils;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JsonUtils {
    private static Gson mGson = new GsonBuilder().serializeNulls().create();

    public static String toJson(Object src) {
        return mGson.toJson(src);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) {
        return mGson.fromJson(json, classOfT);
    }
}
  • toJson方法比较简单,将对象传进来,返回的就是编码后的json字符串
  • fromJson方法比较复杂,第一个入参很简单就是json字符串,第二个参数稍微绕点,表示json串对应的Java对象类型。
    • gson库应该是利用反射技术提取对象类内每个成员的名字类型,然后从json字符串里匹配、提取出字段值。

对应Java类定义

以复杂json消息为例

package com.lanplus.lanova.chassis_control.entity;

import java.util.HashMap;

public class MarkersResponse {
    public String command;
    public String error_message;
    public String status;
    public String type;
    public String uuid;
    public HashMap<String, Marker> results;

    public static class Marker {
        public int floor;
        public int key;
        public String avatar;
        public String marker_name;
        public Pose pose;

        public static class Pose {
            public Orientation orientation;
            public Position position;

            public static class Position {
                public double x;
                public double y;
                public double z;

                public Position() {
                }
            }

            public static class Orientation {
                public double w;
                public double x;
                public double y;
                public double z;

                public Orientation() {
                }
            }

            public Pose() {
            }
        }
        public Marker() {
        }
    }
    public MarkersResponse() {
    }
}

说明

  1. json串里的每个嵌套结构,都对应一个Java内部类,嵌套越深,内部类也越“内部”
  2. 内部类必须是public static修饰的,否则编码时外界无法创建对应类型的Java对象
  3. 每个字段应该设置成private,再提供gettersetter接口,但为了简化代码以便说明问题,就搞成public了。实际项目中可以用lombok库给private字段自动生成getter、setter

编码过程示例

MarkersResponse resp = new MarkersResponse();
MarkersResponse.Marker marker = new MarkersResponse.Marker();
resp.uuid = uuid;
resp.status = "OK";
resp.command = cmd;
resp.results = new HashMap<>();
for (int i = 0; i < 2; i++){
	marker.avatar = String.valueOf(i);
	marker.floor = curFloor;
	marker.key = i;
	marker.marker_name = "marker"+i;
	marker.pose = new MarkersResponse.Marker.Pose();
	marker.pose.orientation = new MarkersResponse.Marker.Pose.Orientation();
	marker.pose.orientation.x = i;
	marker.pose.orientation.y = i;
	marker.pose.orientation.z = i;
	marker.pose.orientation.w = i;
	marker.pose.position = new MarkersResponse.Marker.Pose.Position();
	marker.pose.position.x = i;
	marker.pose.position.y = i;
	marker.pose.position.z = i;
	resp.results.put(marker.marker_name, marker);
}
String msg = JsonUtils.toJson(resp);

解码过程示例

MarkersResponse resp = JsonUtils.fromJson(jsonString, MarkersResponse.class);
// 遍历对象内部字段很简单,除了注意字段可能为null,其他没了

总结

静态类型语言在开发中大型工程时真的比动态类型语言好用太多了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值