week 5 analyse json/xml
前言:
在做web或者其他项目中,JSON与XML格式的数据是大家经常会碰见的2种。在与各种平台做数据对接的时候,JSON与XML格式也是基本的数据传递格式,本文主要简单的介绍JSON/XML文件的读写操作,以及与Bean之间的转换。示例代码都是经过Demo测试的,当然也会把代码上传到GitHub.需要的朋友可以看看。
准备工作
我这里对XML与JSON主要依赖以下2个开源库,当然像针对xml和JSON解析的开源库非常的多,下面这2个感觉相对用起来比较简单。需要注意的是如果缺少下面jar文件中的一个,可能就会出现ClassNotFound 异常,如果发现使用的方法在当前库中找不到,则可能是库版本不同造成的,可以去官网查阅。
1.JSON解析库:
Jackson JSON Processor
官网:http://jackson.codehaus.org/
2.XML解析库 :
Simple XML serialization framework
官网:http://simple.sourceforge.net/home.php
一.JSON简介AVAScript Object Notation是一种轻量级的数据交换格式
具有良好的可读和便于快速编写的特性。
业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持)
JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为。 – Json.org
JSON作为数据是目前网络中主流的数据传输格式之一,应用十分广泛,说是使用率达到99%一点也不勉强
具有良好的可读和便于快速编写的特性。
业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持)
JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为。 – Json.org
JSON作为数据是目前网络中主流的数据传输格式之一,应用十分广泛,说是使用率达到99%一点也不勉强
二.JSON语法
JSON 语法
作用: JSON文本是类似XML文本文件,用来储存和传输数据信息的的媒介
注: JSON同XML一样,不仅可以通过响应文件作为数据的载体,也可以通过满足语法字符串作为对应数据的载体 称之为 “json字符串”
作用: JSON文本是类似XML文本文件,用来储存和传输数据信息的的媒介
注: JSON同XML一样,不仅可以通过响应文件作为数据的载体,也可以通过满足语法字符串作为对应数据的载体 称之为 “json字符串”
json数据存储采用{}与[]语法
{} => java中的双列集合 (字典)
[] => java中的单列集合 (数组)
{} => java中的双列集合 (字典)
[] => java中的单列集合 (数组)
json语法最顶层为 单一{} 或 单一[]
json语法中结构为 {} [] 相互嵌套({}可以嵌套{}[],[]也可以相互嵌套{}[])
json语法中以逗号(,)作为字段分割的标识(注: 最后一个字段不能添加逗号)
字典中语法为 {“key”:value}格式 (注: key为字符串)
多条语句语法:
{
“key1”: value1,
“key2”: value2,
… : … ,
“keyn”: valuen
}
数组中语法为[value1,value2,value3] 格式(注: value拥有类型)
数字(整数或浮点数)
逻辑值(true 或 false)
字符串(在双引号中)
数组(在方括号中)
函数
对象(在大括号中)
null
{}和[]中的每一个value均可以为{}|[] ,且多个value类型不一定相同
逻辑值(true 或 false)
字符串(在双引号中)
数组(在方括号中)
函数
对象(在大括号中)
null
{}和[]中的每一个value均可以为{}|[] ,且多个value类型不一定相同
7.我们在JSON解析中只有三中情况出现
1.{} 解析’大括号’类型
2. [ ] 解析是’中括号’类型
3. 其实只有两种,那第三种则是1与2的组合方法即”{”name”:”小东吖”,”hobby”:[“编程”,”电竞”,”睡觉”]}”那么下面分别来看一些这三种类型以及解析
三.解析JSON
SON解析一定要掌握的两条规则:
1.如果看到是{ }–>使用JSONObject
2.如果看到的[ ]–>使用JSONArray解析
12
2.如果看到的[ ]–>使用JSONArray解析
12
掌握了JSON的数据类型和基本语法后,我们对JSON的各种语法类型进行详细解析(注意掌握两条规则的使用,掌握了JSON解析就那么回事)
// JSON字符串以{}包裹,解析为JSONObject对象 // JSON字符串以[]包裹,解析为JSONArray对象 // 纯数组解析 public static void main(String[] args) { String string = "[\"天津\",\"上海\",\"北京\",\"南京\"]"; // []是数组 将其解析为JSONArray数组即可 拥有数组的方法 JSONArray jsonArray = JSON.parseArray(string); System.out.println(jsonArray); // 纯对象解析 String oString = "{\"name\" : \"小东吖\" }"; // 大括号是对象类型的 解析为JSONObject类型即可 JSONObject jsonObject = JSON.parseObject(oString); // parseObject的参数(字符串,类名.class); 就可解析为对象 Student student = jsonObject.parseObject(oString, Student.class); System.out.println(student);
public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } // toString方法用于控制台输出 @Override public String toString() { return "Student [name=" + name + "]"; }
可以详见博客https://blog.csdn.net/zlsuperjj/article/details/80039143
java中Xml、json之间的相互转换可参见博客:https://www.cnblogs.com/tv151579/p/3516674.html
1.第一种方法(个人实现的)
使用JSON-JAVA提供的方法,之前一直使用json-lib提供的方法转json,后来发现了这个开源项目,觉得用起来很不错,并且可以修改XML.java中的parse方法满足自己的转换需要。
(1)首先去git下载所需的java文件,并导入项目
Git:https://github.com/stleary/JSON-java
(2)使用XML.java中提供的XML.toJSONObject(xml)方法即可完成xml到json的转换,同时也可以对JSON进行格式化
- /* 第一种方法,使用JSON-JAVA提供的方法 */
- //将xml转为json
- JSONObject xmlJSONObj = XML.toJSONObject(xml);
- //设置缩进
- String jsonPrettyPrintString = xmlJSONObj.toString(4);
- //输出格式化后的json
- System.out.println(jsonPrettyPrintString);
2.第二种方法
使用json-lib的XMLSerializer对象
(1)创建XMLSerializer对象
(2)使用XMLSerializer的read(xml)方法即可
- /* 第二种方法,使用json-lib提供的方法 */
- //创建 XMLSerializer对象
- XMLSerializer xmlSerializer = new XMLSerializer();
- //将xml转为json(注:如果是元素的属性,会在json里的key前加一个@标识)
- String result = xmlSerializer.read(xml).toString();
- //输出json内容
- System.out.println(result);
3.测试
- public class Test {
- public static void main(String[] args) {
- String xml = "<class id="
- + "'1'"
- + "><student><name>aaaaaa</name><age>21</age></student><student><name>bbbbbb</name><age>22</age></student></class>";
- /* 第一种方法,使用JSON-JAVA提供的方法 */
- //将xml转为json
- JSONObject xmlJSONObj = XML.toJSONObject(xml);
- //设置缩进
- String jsonPrettyPrintString = xmlJSONObj.toString(4);
- //输出格式化后的json
- System.out.println(jsonPrettyPrintString);
- /* 第二种方法,使用json-lib提供的方法 */
- //创建 XMLSerializer对象
- XMLSerializer xmlSerializer = new XMLSerializer();
- //将xml转为json(注:如果是元素的属性,会在json里的key前加一个@标识)
- String result = xmlSerializer.read(xml).toString();
- //输出json内容
- System.out.println(result);
- }
第一种方法输出:
- {"class": {
- "id": 1,
- "student": [
- {
- "age": 21,
- "name": "aaaaaa"
- },
- {
- "age": 22,
- "name": "bbbbbb"
- }
- ]
- }}
第二种方法输出:
- {"@id":"1","student":[{"name":"aaaaaa","age":"21"},{"name":"bbbbbb","age":"22"}]}
源码下载:http://download.csdn.net/detail/lom9357bye/9690304
json转换成model技巧
在项目中从服务器获取数据的时候,经常采用json格式的数据,为了能方便的使用这些数据,项目中会把json转化为model。
之前我们的项目中是这么用的:
之前我们的项目中是这么用的:
很复杂,很乱,对不对,然而这才只是二十多个字段中的5个,(:зゝ∠),一定有更好的方法。
如果我们能够在动态地去获取对象的属性名就好了,只要json的key和对象的属性名一样,那么就可以利用for循环以可kvc赋值了。在Java中,我们可以利用反射来做到这一点,同样的,在OC中,我们可以利用runtime的特性来实现。
代码如下:
结果如下,DONE!:
如果我们能够在动态地去获取对象的属性名就好了,只要json的key和对象的属性名一样,那么就可以利用for循环以可kvc赋值了。在Java中,我们可以利用反射来做到这一点,同样的,在OC中,我们可以利用runtime的特性来实现。
代码如下:
NSDictionary *dic = @{@"name" : @"小王", @"no" : @"123", @"rank" : @1, @"sex" : @0}; Student *student = [[Student alloc] init]; u_int count; objc_property_t *properties =class_copyPropertyList([Student class], &count); for (int i = 0;i<count;i++) { const char* propertyName =property_getName(properties[i]); NSString *property = [NSString stringWithUTF8String: propertyName]; [student setValue:dic[property] forKey:property]; } free(properties)
结果如下,DONE!:
优点:这种扩展性强,并且与dic存储的类型无关,例如将@"rank" : @1改成@"rank" : @"1"后,也能得到正确的输出。
缺点;但是要求属性名和接口返回json数据中的key一一对应。
扩展一
封装一下,让Model类继承基类就可以直接使用。创建一个JsonModel类,代码如下:
Student *student = [[Student alloc] initWithDic:dic];
缺点;但是要求属性名和接口返回json数据中的key一一对应。
扩展一
封装一下,让Model类继承基类就可以直接使用。创建一个JsonModel类,代码如下:
#import "JsonModel.h" #import "objc/runtime.h" @implementation JsonModel - (id)initWithDic:(NSDictionary *)dic { self = [super init]; if (self) { u_int count; objc_property_t *properties =class_copyPropertyList([self class], &count); for (int i = 0;i<count;i++) { const char* propertyName =property_getName(properties[i]); NSString *property = [NSString stringWithUTF8String: propertyName]; [self setValue:dic[property] forKey:property]; } free(properties); } return self; } @end
使用时,让Student类继承JsonModel类,然后就可以方便的初始化Student类了。
Student *student = [[Student alloc] initWithDic:dic];
扩展二
如果由于各种原因,接口返回数据的key和model的属性名不能统一,那么如何处理呢?初步想法是构造一个映射关系,代码如下:
使用方法:通过重写静态方法getKeyAndPropertyCorrelation去设置关系映射表。
扩展三
github上有一个开源Json解析第三方库JsonModel,包含了很多强大的功能。
如果由于各种原因,接口返回数据的key和model的属性名不能统一,那么如何处理呢?初步想法是构造一个映射关系,代码如下:
#import "JsonModel.h" #import "objc/runtime.h" @implementation JsonModel - (id)initWithDic:(NSDictionary *)dic { self = [super init]; if (self) { u_int count; objc_property_t *properties =class_copyPropertyList([self class], &count); for (int i = 0;i<count;i++) { const char* propertyName =property_getName(properties[i]); NSString *property = [NSString stringWithUTF8String: propertyName]; [self setValue:dic[property] forKey:property]; } free(properties); } return self; } @end
使用方法:通过重写静态方法getKeyAndPropertyCorrelation去设置关系映射表。
扩展三
github上有一个开源Json解析第三方库JsonModel,包含了很多强大的功能。