需要输入的实体示例如下:
/**
* 云打印请求参数
*/
@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
}
参考资料: