余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

JSON的编码风格与常见的应用场景及最佳实战(json模块中常用的四种方法)

xiyangw 2022-11-25 11:40 20 浏览 0 评论

本篇内容包括如下部分内容:JSON编码指南;JSON应用场景;实践经验之谈

1.JSON风格指南

这里的JSON指南,主要推荐的是谷歌的Google JSON风格指南。无论什么语言编程,也通常遵循2/8法则,即遵循好的设计与编码风格,能提前解决80%的问题。关于谷歌的这个JSON编程风格指南手册,可以在如下两个地方找到:

  • 英文版Google JSON Style Guide:https://google.github.io/styleguide/jsoncstyleguide.xml
  • 中文版Google JSON风格指南:https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md

请主要核心点,简单摘录如下:

  • 属性名和值都是用双引号,不要把注释写到对象里面,对象数据要简洁
  • 不要随意结构化分组对象,推荐是用扁平化方式,层次不要太复杂
  • 命名方式要有意义,比如单复数表示
  • 驼峰式命名,遵循Bean规范
  • 使用版本来控制变更冲突
  • 对于一些关键字,不要拿来做key
  • 如果一个属性是可选的或者包含空值或null值,考虑从JSON中去掉该属性,除非它的存在有很强的语义原因
  • 序列化枚举类型时,使用name而不是value
  • 日期要用标准格式处理
  • 设计好通用的分页参数
  • 设计好异常处理

另外,需要关注的内容是JSON API规范,目前该项工作在推进中,取得了很多可喜成果。关于JSON API,这里提几点:

  • JSON API与Google JSON风格指南有很多可以相互参照之处。
  • JSON API是数据交互规范,用以定义客户端如何获取与修改资源,以及服务器如何响应对应请求。
  • JSON API设计用来最小化请求的数量,以及客户端与服务器间传输的数据量。在高效实现的同时,无需牺牲可读性、灵活性和可发现性。
  • JSON API需要使用JSON API媒体类型(application/vnd.api+json) 进行数据交互。
  • JSON API服务器支持通过GET方法获取资源。而且必须独立实现HTTP POST, PUT和DELETE方法的请求响应,以支持资源的创建、更新和删除。
  • JSON API服务器也可以选择性支持HTTP PATCH方法 [RFC5789]和JSON Patch格式 [RFC6902],进行资源修改。JSON Patch支持是可行的,因为理论上来说,JSON API通过单一JSON 文档,反映域下的所有资源,并将JSON文档作为资源操作介质。在文档顶层,依据资源类型分组。每个资源都通过文档下的唯一路径辨识。

规范详情可以参考整理:http://jsonapi.org.cn/format/。

2.JSON应用场景

JSON的使用,依据不同用途,有几个典型的场景:

  1. 内部后台系统之间的数据传输,此种情况下基于HTTP的JSON格式其实没有优势。
  2. 前后台之间的API调用,典型的是前端作为React/VUE/AngularJS/ExtJS等框架做的,前后端使用JSON交互。
  • 此时可以使用类似Dubbox之类的框架,或者原始一些SpringMVC的Controller上直接@ResponseBody或@RestController也可以。
  • 强烈建议在Dubbox之类的rest之上再加一个Nginx转发,这样一些策略的控制,比如同源的控制、简单的缓存策略、安全策略等都可以放到Nginx上来做,也利于多个机器时的负载均衡。
  • 建议使用swaggerUI来自动实现API文档和在线测试。功能很强大,操作简单,而且可以mock接口,在后台没有做好之前,前台就可以先开发了。
  • 可以使用RestUnit或SoapUI来实现自动化测试与压力测试。
  1. 提供给第三方的开发接口API
  2. 基本同上,可以参考Google JSON风格指南与JSON API规范指南。

3.经验之谈

在借助各类工具处理JSON数据时,最常见的其实是大家使用的不规范性,这样碰到各种坑的可能性就很大。根据平时使用Fastjson的经验以及工程师的应用反馈,这里简要总结一下大家常见的问题,归纳如下:

3.1 遵循Java Beans规范与JSON规范

实践告诉我们:遵循beans规范和JSON规范的方式,能减少大部分的问题,比如正确实现setter、getter,用别名就加annotation。注意基本类型的匹配转换,比如在fastjson的issue见到试图把”{“a”:{}}”中的a转换成List的。

3.2 使用正常的key

尽量不要使用数字等字符开头的key,尽量使用符合Java的class或property命名规范的key,这样会减少不必要的冲突。在jsonpath或js里,a.1可能会被解释成a[1]或a[“1”],这些都会带来不必要的麻烦。

3.3 关于日期处理

这一点前面的Google JSON风格指南里也提到了,尽量使用标准的日期格式。或者序列化和反序列化里都是用同样的datePattern格式。

3.4 自定义序列化与反序列化

对于新手来说,自定义序列化是一切罪恶的根源。

尽量不要使用自定义序列化,除非万不得已,优先考虑使用注解过滤,别名等方式,甚至是重新建一个VO类来组装实际需要的属性。使用自定义序列化时一切要小心,因为这样会导致两个问题:

  • 改变了pojo <-> jsonstring 的自然对应关系,从而不利于阅读代码和排查问题,你改变的关系无法简单的从bean和json上看出来了;
  • 反序列化可能出错,因为对应不上原来的属性了。

如果只是序列化发出去(响应)的是JSON数据、传过来(请求)的数据格式跟JSON无关或者是标准的,此时自定义序列化就无所谓了,反正是要接收方来处理。

3.5 JSONObject的使用

JSONObject是JSON字符串与pojo对象转换过程中的中间表达类型,实现了Map接口,可以看做是一个模拟JSON对象键值对再加上多层嵌套的数据集合,对象的每一个基本类型属性是map里的一个key-value,一个非基本类型属性是一个嵌套的JSONObject对象(key是属性名称,value是表示这个属性值的对象的JSONObject)。如果以前用过apache beanutils里的DynamicBean之类的,就知道JSONObject也是一种动态描述Bean的实现,相当于是拆解了Bean本身的结构与数据。这时候由于JSONObject里可能会没有记录全部的Bean类型数据,例如泛型的具体子类型之类的元数据,如果JSONObject与正常的POJO混用,出现问题的概率较高。

下列方式尽量不要使用:

public class TestBean{
 @Setter @Getter
 private TestBean1 testBean1;
 
 @Setter @Getter
 private JSONObject testBean2; // 尽量不要在POJO里用JSONObject
}
``` 
应该从设计上改为都用POJO比较合适:
```java
public class TestBean{
 @Setter @Getter
 private TestBean1 testBean1;
 
 @Setter @Getter
 private TestBean2 testBean2;; // 使用POJO
}
``` 
相对的,写一些临时性的测试代码、demo代码,可以直接全部用JSONObject先快速run起来。
同理,jsonstring中嵌套jsonstring也尽量不要用,例如:
```javascript
{
 "name":"zhangsan",
 "score":"{\"math\":78,\"history\":82}"
}

应该改为全部都是JSON风格的结构:

{
 "name":"zhangsan",
 "score":{
 "math":78,
 "history":82
 }
}

另外,对于jsonstring转POJO(或POJO转jsonstring),尽量使用直接转的方式,而不是先转成JSONObject过渡的方式。特别是对于Fastjson,由于性能优化的考虑,这两个执行的代码是不一样的,可能导致不一样的结果。

String jsonstring = "{\"a\":12}";
// 不推荐这种方式
// 除非这里需要对jsonObject做一些简单处理
JSONObject jsonObject = JSON.parseObject(jsonstring);
A a = jsonObject.toJavaObject(A.class);
// 推荐方式
A a = JSON.parseObject(jsonstring, A.class);

3.6 Hibernate相关问题

懒加载与级联,可能导致出现问题,例如hibernate,建议封装一层VO类型来序列化。使用VO类还有一个好处,就是可以去掉一些没用的属性,减少数据量,同时可以加上额外的属性。

3.7 深层嵌套与泛型问题

尽量不要在使用过多的层次嵌套时使用泛型(List、Map等),可能导致类型丢失,而且问题比较难查。

3.8 抽象类型与子类型问题

尽量不要在同一个Bean的层次结构里使用多个子类型对象,可能导致类型丢失,而且问题比较难查。当然我们可以通过代码显示的传递各种正确的类型,但是这样做引入了更多的不确定性。良好的做法应该是一开始设计时就避免出现这些问题。

3.9 避免循环引用

尽量避免循环引用,这个虽然可以通过序列化特性禁掉,但是如果能避免则避免。

3.10 注意编码和不可见字符

对于InputStream、OutputStream的处理,有时候会报一些奇怪的错误,not match之类的,这时候也许我们看日志里的json字符串可能很正常,但就是出错。

这时可能就是编码的问题了,可能是导致字符错乱,也可能是因为UTF-8文件的BOM头,这些潜在的问题可能在二进制数据转文本的时候,因为一些不可见字符无法显示,导致日志看起来只有正常字符而是正确的,问题很难排查。

处理办法就是按二进制的方式把Stream保存起来,然后按hex方式查看,看看是否有多余字符,或者其他错误。

以上为我们在实际JSON编程中应该关注和推荐的方面和方法,希望对你有帮助。

相关推荐

JavaScript入门(Javascript入门经典第七版)
JavaScript入门(Javascript入门经典第七版)

什么是JavaScriptJavaScript是一门函数优先的轻量级、解释型的编程语言。运行的环境需要浏览器的支持。JavaScript是在1995年由...

2023-03-21 18:23 xiyangw

JavaScript需要掌握的技能盘点(JS入门需看)(javascript学会了能做什么)
JavaScript需要掌握的技能盘点(JS入门需看)(javascript学会了能做什么)

JavaScript是当今使用的最重要的Web开发语言之一。它使您可以为您的网站添加广泛的功能特性,从最基本得到最高级的。因此,无论您是专家级开发人员还是刚...

2023-03-21 18:22 xiyangw

Web前端:JavaScript最强总结,最全面的零基础入门教程
Web前端:JavaScript最强总结,最全面的零基础入门教程

JavaScript是网景(Netscape)公司开发的一种基于客户端浏览器、面向(基于)对象、事件驱动式的网页脚本语言。JavaScript语言的前身叫作L...

2023-03-21 18:22 xiyangw

分享几个在线学习代码的网站,每天掌握一种编程
分享几个在线学习代码的网站,每天掌握一种编程

站长寄语站长今天看到一句话很不错,墙有三重,一重是网络层面,二重是外语层面,三重是心态层面,只有打破这三重的束缚,才真正是拥抱了自由,站长今天为大家推荐几个学习...

2023-03-21 18:21 xiyangw

零基础学数控M代码篇(一)(数控编程m代码大全与详解)
零基础学数控M代码篇(一)(数控编程m代码大全与详解)

前面的文章讲解了常用的G代码指令,本章开始讲解M代码,M代码又称为辅助功能,主要控制机床加工过程的辅助动作,以便更好的完成加工过程。下图为铣床(加工中心)常用的...

2023-03-21 18:21 xiyangw

每个学习C语言的人都学过的代码,小白必学(c语言编程入门代码)
每个学习C语言的人都学过的代码,小白必学(c语言编程入门代码)

本文以VS2015为例,需要工具的往下看学习一门程序设计语言的惟一途径就是使用它编写程序,但是如果一开始就面对一个复杂的程序,并详尽的介绍语言的方方面面,将会涉...

2023-03-21 18:20 xiyangw

初学者编程 求阶乘(用编程计算阶乘)
初学者编程 求阶乘(用编程计算阶乘)

时间限制:1s空间限制:128000KB题目等级:青铜Bronze题目描述Description输入n,输出n的阶乘,n<=1...

2023-03-21 18:20 xiyangw

一分钟让你懂Go语言,快速上手编写高效程序!
一分钟让你懂Go语言,快速上手编写高效程序!

在当今互联网时代,Go语言以其高性能、高并发和简洁易学等特点,成为了软件开发的热门选择。从谷歌(Google)推出Go语言以来,它已经经历了多个版本的迭代升级,...

2023-03-21 18:20 xiyangw

用汉字编程写代码(汉字程序代码)
用汉字编程写代码(汉字程序代码)

作者:小傅哥博客:https://bugstack.cn-包含:Java基础,面经手册,Netty4.x,手写Spring,用Java实现JVM,重学...

2023-03-21 18:19 xiyangw

大学生怎么开始学习编程?(大学生怎样自学编程)
大学生怎么开始学习编程?(大学生怎样自学编程)

小编推荐c/c++编程交流群:941636044那时刚进入大学,对C语言、编程什么的一点都不感冒。加上自己打字很慢,敲起代码来,就跟蜗牛一样,对编程提不起兴趣来...

2023-03-21 18:19 xiyangw

编程练习题第五天,C语言代码,算法竞赛入门,UVa1225
编程练习题第五天,C语言代码,算法竞赛入门,UVa1225

原题原题:Trungisboredwithhismathematicshomeworks.Hetakesapieceofchalkan...

2023-03-21 18:19 xiyangw

初学者如何去理解编程的世界和编程代码的原理呢?
初学者如何去理解编程的世界和编程代码的原理呢?

前面我们给大家介绍了编程的世界,即编程运行的环境,以及代码的含义,今天呢给大家介绍一下编程中的代码究竟是个什么东西?以及它的原理是什么?我们都知道编程的逻辑大抵...

2023-03-21 18:18 xiyangw

想学习编程但是看不懂代码该怎么办(编程看不懂代码什么意思先看什么)
想学习编程但是看不懂代码该怎么办(编程看不懂代码什么意思先看什么)

实际上有不少编程的初学者都面临这样一个问题,自身对于编程还是比较有兴趣的,但是一看到各种程序代码就打退堂鼓了,感觉难度太大,不知道该从哪里开始学习。在学习编程的...

2023-03-21 18:18 xiyangw

入门C++,代码生成的过程你知道吗?(c代码生成流程图)
入门C++,代码生成的过程你知道吗?(c代码生成流程图)

易道云出品在此,小编与大家聊一聊代码的生成过程。[小鼓掌]代码生成主要包括三步:预编译、编译、链接和载入[奋斗]预编译:主要包括宏替换、文件包含和条件编译三个部...

2023-03-21 18:17 xiyangw

命名不善的代码会有多坑?这段Python官方入门教程的例程是个典型
命名不善的代码会有多坑?这段Python官方入门教程的例程是个典型

看过Python3官方入门的同学也许对这段代码有印象:大多数读者也许都认为这些字符串和数字并没有特别意义。如果真是这样,这个例程还不如用“dict={'a...

2023-03-21 18:17 xiyangw

取消回复欢迎 发表评论: