Gson按指定字段顺序序列化

需要输入的实体示例如下:

/**
 * 云打印请求参数
 */
@Data
public class YiRuiPrintResParam extends YiRuiCommonResParam implements Serializable {
    private String deviceName;
    private String token;
    private String transNo;
    private Integer type;
    private Nc nc;
    private String pc;
}
/**
 * 公共请求参数
 */
@Data
public class YiRuiCommonResParam implements Serializable {
    private String productKey;
    private Long timestamp;
    private String signMethod;
    private String sign;
}
@Data
public class Nc {
    private Integer channel;
    private String ct;
    private String charset;
}

如果没有指定顺序,Gson会按实体类里的字段排列顺序来序列化(与字段设值顺序无关),包括里面的类Nc的输出字段顺序也是如此。

序列化输出代码:

Gson printGson = new Gson();
String printReq = printGson.toJson(printParam);
System.out.printf("云打印 request:%s\n", printReq);

序列化输出结果:

{
    "deviceName": "8115210800100022",
    "token": "E75x+wmRF3eyo1IZxnn+s2PrhtAYIhX1Kchk9eVtx1niQulJx4QgUwYoYCe7Fugv1634089348814",
    "transNo": "20211013141142",
    "type": 0,
    "nc": {
        "channel": 1,
        "ct": "12345",
        "charset": "abcde"
    },
    "pc": "{\"ct\":[{\"cols\":[{\"cv\":\"\"}],\"tp\":\"0\"},{\"tp\":\"3\"},{\"cols\":[{\"cv\":\"商户名称:\"},{\"cv\":\"测试商户\"}],\"tp\":\"1\"},{\"cols\":[{\"cv\":\"金额RMB:\"},{\"cv\":\"0.01元\"}],\"tp\":\"1\"}],\"cn\":1}",
    "productKey": "78d077bf960c477b",
    "timestamp": 1634105502,
    "signMethod": "MD5",
    "sign": "394009CE36A0AD145D279AF84131E35D"
}

如果想指定顺序,应该如何实现呢?本人的需求是按字段的英文名称作为升序排序,参考了网上的一些做法,都是偏向于通过继承TypeAdapter类来实现,具体做法如下:

/**
 * 打印适配器
 */
public class YiRuiPrintAdapter extends TypeAdapter<YiRuiPrintResParam> {

    @Override
    public void write(JsonWriter out, YiRuiPrintResParam param) throws IOException {
//        Class<? extends Nc> ncClazz = param.getNc().getClass();
//        Field[] ncFields = ncClazz.getDeclaredFields();

        out.beginObject();

        // 按自定义顺序输出字段信息
        out.name("deviceName").value(param.getDeviceName());
        out.name("nc");

        out.beginObject();
        out.name("channel").value(param.getNc().getChannel());
        out.name("charset").value(param.getNc().getCharset());
        out.name("ct").value(param.getNc().getCt());
//        setWrite(ncFields, out, param.getNc());
        out.endObject();

        out.name("pc").value(param.getPc());
        out.name("productKey").value(param.getProductKey());
        out.name("sign").value(param.getSign());
        out.name("signMethod").value(param.getSignMethod());
        out.name("timestamp").value(param.getTimestamp());
        out.name("token").value(param.getToken());
        out.name("transNo").value(param.getTransNo());
        out.name("type").value(param.getType());

        out.endObject();
    }

    @Override
    public YiRuiPrintResParam read(JsonReader jsonReader) throws IOException {
        return null;
    }

//    /**
//     * 递归写入属性
//     *
//     * @param fields
//     * @param out
//     * @param object
//     * @return void
//     * @author liangzhaolinC
//     * @date 2021/10/13 10:50
//     */
//    public void setWrite(Field[] fields, JsonWriter out, Object object) {
//        for (int i = 0; i < fields.length; i++) {
//            Field field = fields[i];
//            field.setAccessible(true);
//            try {
//                Object type = field.get(object);
//                if (type == null) {
//                    continue;
//                }
//                if (!(type instanceof String)) {
//                    out.name(field.getName()).beginObject();
//                    Field[] subFields = type.getClass().getDeclaredFields();
//                    setWrite(subFields, out, type);
//                    out.endObject();
//                } else {
//                    out.name(field.getName()).value(type.toString());
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }
}

out.beginObject(); 的意思是json里加上左括号 {

out.endObject(); 的意思是json里加上右括号 }

out.name("nc"); 的意思是json里加上key "nc"

out.value(xxx); 的意思是json里加上value "xxx"

可以看下对应里面的源码理解下。

代码中已注释的代码部分,其实是为了想自动把Nc类里的字段打印出来,但因为代码是参考网上的,尝试的时候遇到点bug,项目比较急,所以先注释掉,待以后再研究(如果有小伙伴能修复也麻烦分享下)。取而代之的是将Nc的字段序列化顺序也是通过写死来控制。所以才有第二次 out.beginObject(); 的调用,和对应的 out.endObject();

序列化代码:

Gson printGson = new GsonBuilder().registerTypeAdapter(YiRuiPrintResParam.class, new YiRuiPrintAdapter()).create();
String printReq = printGson.toJson(printParam);
System.out.printf("云打印 request:%s\n", printReq);

序列化输出结果:

{
    "deviceName": "8115210800100022",
    "nc": {
        "channel": 1,
        "charset": "abcde",
        "ct": "12345"
    },
    "pc": "{\"ct\":[{\"cols\":[{\"cv\":\"\"}],\"tp\":\"0\"},{\"tp\":\"3\"},{\"cols\":[{\"cv\":\"商户名称:\"},{\"cv\":\"测试商户\"}],\"tp\":\"1\"},{\"cols\":[{\"cv\":\"金额RMB:\"},{\"cv\":\"0.01元\"}],\"tp\":\"1\"}],\"cn\":1}",
    "productKey": "78d077bf960c477b",
    "sign": "F6093E0B127D6B537D8BDD376C532097",
    "signMethod": "MD5",
    "timestamp": 1634106351,
    "token": "E75x+wmRF3eyo1IZxnn+s2PrhtAYIhX1Kchk9eVtx1niQulJx4QgUwYoYCe7Fugv1634089348814",
    "transNo": "20211013142551",
    "type": 0
}

参考资料:

java自定义Gson生成json字符串的顺序

gson改变输出字段的顺序

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllenLeungX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值