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语法
JSON 语法
作用: JSON文本是类似XML文本文件,用来储存和传输数据信息的的媒介
注: JSON同XML一样,不仅可以通过响应文件作为数据的载体,也可以通过满足语法字符串作为对应数据的载体 称之为 “json字符串”
json数据存储采用{}与[]语法
{} => java中的双列集合 (字典)
[] => java中的单列集合 (数组)

json语法最顶层为 单一{} 或 单一[]
json语法中结构为 {} [] 相互嵌套({}可以嵌套{}[],[]也可以相互嵌套{}[])
json语法中以逗号(,)作为字段分割的标识(注: 最后一个字段不能添加逗号)
字典中语法为 {“key”:value}格式 (注: key为字符串)
多条语句语法:
{
“key1”: value1,
“key2”: value2,
 …  :  … ,
 “keyn”: valuen
}
数组中语法为[value1,value2,value3] 格式(注: value拥有类型)
数字(整数或浮点数)
逻辑值(true 或 false)
字符串(在双引号中)
数组(在方括号中)
函数
对象(在大括号中)
null
{}和[]中的每一个value均可以为{}|[] ,且多个value类型不一定相同

7.我们在JSON解析中只有三中情况出现
 1.{} 解析’大括号’类型 
 2. [ ] 解析是’中括号’类型 
 3. 其实只有两种,那第三种则是1与2的组合方法即”{”name”:”小东吖”,”hobby”:[“编程”,”电竞”,”睡觉”]}”那么下面分别来看一些这三种类型以及解析
三.解析JSON
SON解析一定要掌握的两条规则:
1.如果看到是{ }–>使用JSONObject
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进行格式化

[java] view plain copy
 
  1. /* 第一种方法,使用JSON-JAVA提供的方法 */  
  2.        //将xml转为json  
  3.        JSONObject xmlJSONObj = XML.toJSONObject(xml);  
  4.        //设置缩进  
  5.        String jsonPrettyPrintString = xmlJSONObj.toString(4);  
  6.        //输出格式化后的json  
  7.        System.out.println(jsonPrettyPrintString);  



2.第二种方法

使用json-lib的XMLSerializer对象

(1)创建XMLSerializer对象

(2)使用XMLSerializer的read(xml)方法即可

[java] view plain copy
 
  1. /* 第二种方法,使用json-lib提供的方法 */  
  2.  //创建 XMLSerializer对象  
  3.  XMLSerializer xmlSerializer = new XMLSerializer();  
  4.  //将xml转为json(注:如果是元素的属性,会在json里的key前加一个@标识)  
  5.  String result = xmlSerializer.read(xml).toString();  
  6.  //输出json内容  
  7.  System.out.println(result);  

 

3.测试

[java] view plain copy
 
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         String xml = "<class id="  
  4.                 + "'1'"  
  5.                 + "><student><name>aaaaaa</name><age>21</age></student><student><name>bbbbbb</name><age>22</age></student></class>";  
  6.   
  7.         /* 第一种方法,使用JSON-JAVA提供的方法 */  
  8.         //将xml转为json  
  9.         JSONObject xmlJSONObj = XML.toJSONObject(xml);  
  10.         //设置缩进  
  11.         String jsonPrettyPrintString = xmlJSONObj.toString(4);  
  12.         //输出格式化后的json  
  13.         System.out.println(jsonPrettyPrintString);  
  14.   
  15.         /* 第二种方法,使用json-lib提供的方法 */  
  16.         //创建 XMLSerializer对象  
  17.         XMLSerializer xmlSerializer = new XMLSerializer();  
  18.         //将xml转为json(注:如果是元素的属性,会在json里的key前加一个@标识)  
  19.         String result = xmlSerializer.read(xml).toString();  
  20.         //输出json内容  
  21.         System.out.println(result);  
  22.   
  23.     }  

 

第一种方法输出:

[java] view plain copy
 
  1. {"class": {  
  2.     "id": 1,  
  3.     "student": [  
  4.         {  
  5.             "age": 21,  
  6.             "name": "aaaaaa"  
  7.         },  
  8.         {  
  9.             "age": 22,  
  10.             "name": "bbbbbb"  
  11.         }  
  12.     ]  
  13. }}  


第二种方法输出:

[java] view plain copy
 
    1. {"@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的特性来实现。
代码如下:
  
    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类,代码如下:
#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的属性名不能统一,那么如何处理呢?初步想法是构造一个映射关系,代码如下:
#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,包含了很多强大的功能。
posted @ 2019-03-29 14:29  肥鹤不只是肉多还追光  阅读(218)  评论(0编辑  收藏  举报