JSON: 是JavaScript Object Notation(JavaScript 对象表示法),它是一种数据交换格式。
JSON 是存储和交换文本信息的语法。类似 XML。
JSON 比 XML 更小、更快,更易解析。
JSON基础结构
因为JSON使用JavaScript语法,所以无需额外的软件就能处理JavaScript中的JSON。
JSON还规定了字符集必须是UTF-8 。为了统一解析,JSON的字符串规定必须用双引号""
,Object的键也必须用双引号""
。
在JSON中,一共就这么几种数据类型:
- number:和JavaScript的number完全一致;
- boolean:就是JavaScript的
true
或false
; - string:就是JavaScript的string;
- null:就是JavaScript的null;
- array:就是JavaScript的Array表示方式——
[]
; - object:就是JavaScript的
{ ... }
表示方式。
把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能够通过网络传递给其他计算机。
如果我们收到一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用这个对象了。
JSON对象结构
语法:var obj = {"键" : "值","键" : "值","键" : "值"}
说明:obj 指的是json对象,对象结构以 { 开头,到 } 结束。其中键名和值之间用冒号构成对,键值对用逗号分隔。
注意,这里的键名是字符串,但是值可以是数字、字符串、布尔值、数组、对象和null。
JSON数组结构
语法:var arr = [ {"键名" : "值","键名" : "值"}, {"键名" : "值","键名" : "值"} ]
说明:arr指的是json数组,数组结构是以 [ 开始,到 ] 结束。在JSON数组中,每一对 { } 相当于一个JSON对象。
特殊情况
1. JSON 不能存储 Date 对象。
① 如果要存储 Date 对象,需要将其转换为字符串。之后再将字符串转换为 Date 对象。
var text = '{ "name":"Runoob", "birthday":"2013-12-14"}';
var obj = JSON.parse(text);
obj.birthday = new Date(obj.birthday);
$('#demo').text("姓名: " obj.name + "生日: " + obj.birthday);
② js将从后台得到的时间戳(毫秒数)转换为日期格式。
var date = new Date( data.time ) ; //括号里的data就是后端传回来的格式有问题的时间数据
dateFormat= date .toLocaleString(); //默认格式为" 年 / 月 / 日 上/ 下午 时:分:秒 "
如果希望转换为" 年-月-日 时:分:秒 "的格式,可以自己定义一个方法。
function add0(m) {
return m < 10 ? '0' + m : m;
}
function formatDate(timeStamp) {
let time = new Date(timeStamp),
y = time.getFullYear(),
m = time.getMonth() + 1,
d = time.getDate(),
h = time.getHours(),
mm = time.getMinutes(),
s = time.getSeconds();
return y + '-' + add0(m) + '-' + add0(d) + ' ' + add0(h) + ':' + add0(mm) + ':' + add0(s);
//顾名思义,将小于10的时间前面加个0,即9:5:43改成09:05:43
}
}
2. JSON 不允许包含函数,但你可以将函数作为字符串存储,之后再将字符串转换为函数。
var text = '{ "name":"Runoob", "alexa":"function () {return 10000;}", "site":"www.runoob.com"}';
var obj = JSON.parse(text);
obj.alexa = eval("(" + obj.alexa + ")");
document.getElementById("demo").innerHTML = obj.name + " Alexa 排名:" + obj.alexa();
JSON序列化与反序列化
JSON,大部分是用来处理JavaScript和Web服务端之间的数据交换,把后台Web服务端的数据传递到前台,然后使用JavaScript语法进行处理,例如Ajax等。
由于JSON语法是Javascript语法的子集,JavaScript函数 eval() 可用于将JSON文本转换为JavaScript对象。
前端中的JSON序列化
1. JavaScript对象序列化成JSON格式的字符串
var obj= {
name: 'mephisto',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
① var str = obj.toJSONString();
② var str = JSON.stringify(obj);
要输出得好看一些,可以加上参数,按缩进输出:
JSON.stringify(mephisto, null, ' ');
{
"name": "mephisto",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
第二个参数用于控制如何筛选对象的键值,如果我们只想输出指定的属性,可以传入Array;
JSON.stringify(mephisto, ['name', 'skills'], ' ');
{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
还可以传入一个函数,这样对象的每个键值对都会被函数先处理:
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringify(xiaoming, convert, ' ');
上面的代码把所有属性值都变成大写:
{
"name": "mephisto",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" MIDDLE SCHOOL",
"skills": [
"JAVASCRIPT",
"JAVA",
"PYTHON",
"LISP"
]
}
如果我们还想要精确控制如何序列化,可以给mephisto
定义一个toJSON()
的方法,直接返回JSON应该序列化的数据:
var xiaoming = {
name: 'mephisto',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只输出name和age,并且改变了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"mephisto","Age":14}'
2. JSON格式的字符串反序列化成一个JavaScript对象
var str = '{ "name" : "logo" , "age" : 12}';
① var obj = eval( "(" + str + ")" ); 必须把文本包含在括号中,这样才能避免语法错误。
② var obj = JSON.parse(str);
③ var obj = str.parseJSON(); 需要JSON.js文件
JSON.parse() 还可以接收一个函数,用来转换解析出的属性:
var obj = JSON.parse('{"name":"小明","age":14}', function (key, value) {
if (key === 'name') {
return value + '同学';
}
return value;
});
console.log(JSON.stringify(obj)); // {name: '小明同学', age: 14}
net.sf.json-lib 解析
Json-lib 需要的 jar 包:
- commons-beanutils-1.8.3.jar
- commons-collections-3.2.1.jar
- commons-lang-2.6.jar
- commons-logging-1.1.1.jar
- ezmorph-1.0.6.jar
- json-lib-2.4-jdk15.jar
依赖:
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<!-- 下面两个必须要写,且jdk15不能写成别的 -->
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
序列化:
- JavaBean →→→→ JSON格式字符串
Object obj = new Object();
JSONObject jsonObj = JSONObject.fromObject(obj);
String str = jsonObj.toString();
- Java数组 / List集合 →→→→ JSON格式字符串
Item[] items = {item1,item2,item3};
List<Person> list = new ArrayList<Person>();
JSONArray jsonArr = JSONArray.fromObject(items);
JSONArray jsonArr = JSONArray.fromObject(list);
String str = jsonArr.toString();
- Java的Map集合 →→→→ JSON格式字符串
Map<String,Item> map = new HashMap<String,Item>();
JSONObject jsonObject = JSONObject.fromMap(map); //方式一
JSONObject jsonObject = JSONObject.fromObject(map); //方式二
String str = jsonObject.toString();
反序列化:
- JSON格式字符串 →→→→ JavaBean / Map
在将 Json 形式的字符串转换为 JavaBean 的时候需要注意 JavaBean 中必须有无参构造函数。
String jsonObject = "{'name':'李书豪','age':24}";
Person person = (Person) JSONObject.toBean(jsonObject, Person.class);
Map<String, Object> map = (Map<String, Object>) JSONObject.toBean(jsonObject, Map.class);
- JSON格式字符串 →→→→ Java数组 / List集合
String jsonStr = " [ …… ] ";
JSONArray jsonArr = JSONArray.fromObject(jsonStr);
List<Person> person = (List<Person>) JSONArray.toCollection(jsonArr,Person.class);
org.json 解析
依赖:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<!-- 不写下面的版本会报错 -->
<version>20170516</version>
</dependency>
- 序列化:
JSONObject strJson = new JSONObject(jsonStr); // 传入字符串
JSONObject beanJson = new JSONObject(student); // 传入Bean类型
JSONObject mapJson = new JSONObject(map); // 传入Map类型
JSONArray strJson = new JSONArray(jsonStr); // 传入字符串
JSONArray mapJson = new JSONArray(list); // 传入Collection类型
JSONArray arrayJson = new JSONArray(numlist); // 传入Array类型
- 反序列化:
JSONObject jObject=jsonArray2.getJSONObject(user);
Student student=new Student(jObject.getInt("id"), jObject.getString("name"),jObject.getInt("age"));
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
jsonObject = jsonArray.getJSONObject(i);
String name = jsonObject.getString("name");
int age = jsonObject.getInt("age");
}
- JSONObject 根据Key获取Value值
// 创建JSON解析对象
JSONObject obj = new JSONObject(jsonObj);
// obj.后面有各种数据类型,根据对象来选择使用的数据类型
String name = obj.getString("name");
// 同理如上,这里的age为Int类型,我们就用对应的类型进行解析
int age = obj.getInt("age");
- JSONObject 添加JSON
//向json对象中添加JavaBean对象或者任意类型数据
JSONObject testObj2 = jsonObject.put("name", "fyj");
- JSONArray 遍历
JSONArray jArray = new JSONArray(jsonArr);
for (int i = 0; i < jArray.length; i++) {
String string = jArray.getString(i);
}
- 向JSONArray中添加JSON对象
JSONObject obj1 = new JSONObject(object1);
JSONObject obj2 = new JSONObject(object2);
jArray.add(obj1);
jArray.add(obj2);
Gson 解析
GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。
主要特点:
- 快速、高效
- 代码量少、简洁
- 面向对象
- 数据传递和解析方便
Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。
依赖:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
基本类型的序列化
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
Java Bean、List、Map序列化成 Json字符串
Gson gson = new Gson();
String str = gson.toJson(obj);
List<PersonJson> list = new ArrayList<>();
Map<String,PersonJson> map = new HashMap<>();
String str = gson.toJson(list);
String str = gson.toJson(map)
基本类型的反序列化
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("99.99", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class); // true
String str = gson.fromJson("str", String.class); // String
json字符串反序列化为JavaBean
Gson gson = new GsonBuilder().create();
PersonJson p = gson.fromJson(jsonStr,PersonJson.class);
json字符串反序列化为List集合
Gson gson = new GsonBuilder().create();
List<PersonJson> list = gson.fromJson(listJsonStr,new TypeToken<ArrayList<PersonJson>>(){}.getType());
Jackson 解析
Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。
主要特点:
- 容易使用 - jackson API提供了一个高层次外观,以简化常用的用例。
- 无需创建映射 - API提供了默认的映射大部分对象序列化。
- 性能高 - 快速,低内存占用,适合大型对象图表或系统。
- 干净的JSON - jackson创建一个干净和紧凑的JSON结果,这是让人很容易阅读。
- 不依赖 - 库不需要任何其他的库,除了JDK。
- 开源代码 - jackson是开源的,可以免费使用。
依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
创建实体类:
/**
* @Description: JSON序列化和反序列化User类
*
*/
public class User {
/**
* JSON注解 Jackson提供了一系列注解,方便对JSON序列化和反序列化进行控制,下面介绍一些常用的注解。
*
* @JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。
* @JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd
* HH-mm-ss")。
* @JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty("name")。
*/
@JsonIgnore
private Integer id;
@JsonProperty("name")
private String trueName;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthday;
private String email;
。。。省略getset方法、toString()方法等
序列化:
User u1 = new User();
u1.setId(1);
u1.setTrueName("curry");
u1.setAge(30);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
u1.setBirthday(dateFormat.parse("1988-9-21"));
u1.setEmail("138@163.com");
/**
* ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
* ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
* writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
* writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
* writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
* writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。
*/
ObjectMapper mapper = new ObjectMapper();
//User对象转Json,
String jsonValue = mapper.writeValueAsString(u1);
System.out.println(jsonValue);
//输出{"age":30,"birthday":"1988-09-20 16:00:00","email":"138@163.com","name":"curry"}
//List集合转Json
List<User> users = new ArrayList<>();
users.add(u1);
users.add(u2);
String jsonList = mapper.writeValueAsString(users);
System.out.println(jsonList);
//输出[{"age":30,"birthday":"1988-09-20 16:00:00","email":"138@163.com","name":"curry"},{"age":29,"birthday":"1989-09-20 16:00:00","email":"123@qq.com","name":"KD"}]
反序列化:
/**
* ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。
*/
String json = " {\"id\":3, \"name\":\"小明\", \"age\":18, \"birthday\":590774400000, \"email\":\"xiaomin@sina.com\"} ";
ObjectMapper mapper2 = new ObjectMapper();
User user = mapper2.readValue(json, User.class);
System.out.println(user.toString());
//输出User [id=null, trueName=小明, age=18, birthday=Wed Sep 21 00:00:00 CST 1988, email=xiaomin@sina.com]
FastJson 解析
fastJson是由阿里巴巴开发的一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。fastJson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。
主要特点:
- 快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)
- 强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)
- 零依赖(没有依赖其它任何类库除了JDK)
依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.37</version>
</dependency>
序列化:
- 序列化Java Bean
String objJson = JSON.toJSONString(Object object);
// 缺省情况下fastJSON不序列化值为Null的字段
User user = new User();
user.setTrueName("李四");
user.setAge(24);
String userJson = JSON.toJSONString(user);
System.out.println(userJson); //{"age":24,"trueName":"李四"}
user.setId(111);
userJson = JSON.toJSONString(user);
System.out.println(userJson); //{"age":24,"id":111,"trueName":"李四"}
user.setEmail("98@98");
//传入一个boolean值,可以输出格式化后的 JSON 字符串
userJson = JSON.toJSONString(user,true);
System.out.println(userJson);
{
"age":24,
"email":"98@98",
"id":111,
"trueName":"李四"
}
- 序列化list集合
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map1 = new HashMap<String, Object>();
map1.put("key1", "One");
map1.put("key2", "Two");
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("key1", "Three");
map2.put("key2", "Four");
list.add(map1);
list.add(map2);
String listJson = JSON.toJSONString(list);
//输出 [{"key1":"One","key2":"Two"},{"key3":"Three","key4":"Four"}]
- 序列化Map
Map<String, Object> map = new HashMap<String, Object>();
map.put("key1", "One");
map.put("key2", "Two");
String mapJson = JSON.toJSONString(map,true);
fastJson 的几个常用特性:
- 日期格式化
fastJson可以直接对日期类型格式化,在缺省的情况下,fastJson会将Date转成long。
String dateJson = JSON.toJSONString(new Date());
System.out.println(dateJson); //1401370199040
使用SerializerFeature特性格式化日期。
String dateJson = JSON.toJSONString(new Date(), SerializerFeature.WriteDateUseDateFormat);
System.out.println(dateJson); //"2014-05-29 21:36:24"
也可以指定输出日期格式。
String dateJson = JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(dateJson); //"2014-05-29 21:47:00.154"
- 使用单引号
String listJson = JSON.toJSONString(list, SerializerFeature.UseSingleQuotes);
// 输出:[{'key1':'One','key2':'Two'},{'key3':'Three','key4':'Four'}]
- 格式化
String listJson = JSON.toJSONString(list, SerializerFeature.PrettyFormat);
- 输出null字段
String listJson = JSON.toJSONString(map, SerializerFeature.WriteMapNullValue);
// {"a":null,"b":1}
- 序列化时写入类型信息
User user = new User();
user.setAge(18);
user.setUserName("李四");
String listJson = JSON.toJSONString(user, SerializerFeature.WriteClassName);
// 输出结果:{"@type":"User","age":18,"userName":"李四"}
// 由于序列化带了类型信息,使得反序列化时能够自动进行类型识别。
将上面的例子反序列化
User user1 = (User) JSON.parse(listJson);
System.out.println(user1.getAge());
// 输出18
// 如果User序列化时没有加入类型信息(SerializerFeature.WriteClassName),按照上面的做法就会报错(java.lang.ClassCastException)。
反序列化:
- 对象反序列化
User user1 = JSON.parseObject(userJson, User.class);
System.out.println(user1.getTrueName());
System.out.println(user1);
// 李四
// User [id=111, trueName=李四, age=24, birthday=null, email=98@98]
- 集合反序列化
List<User> list1 = JSON.parseArray(listJson, User.class);
- Map反序列化
Map<String, Object> map1 = JSON.parseObject(mapJson, new TypeReference<Map<String, Object>>(){});