@


JSON解析与序列化

JSON(JavaScript Object Notation),是一种并轻量级的数据交换格式。它以一种规定格式的字符串进行数据交换,其本身在传输和解析效率上都要高于XML方式,Android提供的JSON解析方式速度慢,一般采用其它开源库中更快的解析方式,比如Gson、JackJson和FastJson。

//JSON对象
{
	"name":"zhangsan"
	"age":"23",
	"sex":"男"
}
//JSON数组
[
	{
		"name":"zhangsan"
		"age":"23",
		"sex":"男"
	},
	{
		"name":"lisi"
		"age":"13",
		"sex":"女"
	},
	{
		"name":"wangwu"
		"age":"23",
		"sex":"男"
	}
]


Android原生

//获取JSON对象
try {
	JSONObject jsonObject = new JSONObject(string);
	String name = jsonObject.getString("name");
	int age = jsonObject.getInt("age");
	String sex = jsonObject.getString("sex");
} catch (JSONException e) {
    e.printStackTrace();
}
//获取JSON数组
try {
    JSONArray array = new JSONArray(string);
    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < array.length(); i++) {
        JSONObject object = array.getJSONObject(i);
        String name = object.getString("name");
        int age = object.getInt("age");
        String sex = object.getString("sex");
        buffer.append("name:" + name + "  age:" + age + "  sex:" + sex + "\n");
	}
} catch (JSONException e) {
    e.printStackTrace();
}
//对象转为JSON字符串
//数组(列表)转为JSON字符串

Gson

Gson是Google出品的Json解析函数库,可以将JSON字符串反序列化为对应的Java对象,或者反过来将Java对象序列化为对应的字符串,免去了开发者手动通过JSONObject和JSONArray将Json字段逐个进行解析的烦恼,也减少了出错的可能性,增强了代码的质量。使用gson解析时候,对应的Java实体类无需要使用注解进行标记,支持任意复杂Java对象包括没有源代码的对象。

//依赖
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
//Java Bean
class User{
	private int age;
    private String name;
    private String sex;
    
	public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
}
	
//获取JSON对象
Gson gson = new Gson();
User user= gson.fromJson(jsonData, User.class); 

//获取JSON数组
Gson gson = new Gson();
List<User> appList = gson.fromJson(jsonData, new TypeToken<List<User>>() {}.getType());
//对象转为JSON字符串
//数组(列表)转为JSON字符串

FastJson

fastjson是阿里巴巴公司出品的一个java语言编写的高性能且功能完善的JSON函数库,他采用一种“假定有序快速匹配”的算法,把JSON parse的性能提升到极致,号称是目前java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化,协议交互。Web输出、Android客户端等多种应用场景
Fastjson特点是:用Java语言编写的高性能功能完善的JSON库。它采用了一种“假定有序、快速匹配”的算法

//依赖
implementation 'com.alibaba:fastjson:1.1.55.android'
//获取JSON对象
//第一种
JSONObject jsonObject = JSONObject.parseObject(string);
String jsonString = JSONObject.toJSONString(jsonObject);
//第二种
User user= JSONObject.parseObject(string, new TypeReference<User>() {});
//第三种
User user= JSONObject.parseObject(string, User.class);
//获取JSON数组
JSONArray jsonArray = JSONArray.parseArray(string);
for (Object obj : jsonArray) {
	JSONObject jsonObject = (JSONObject) obj;
}
//对象转为JSON字符串
Teacher teacher = new Teacher();
String jsonString = JSONObject.toJSONString(teacher);
//数组(列表)转为JSON字符串
Student student = new Student("lily", 12);
Student studenttwo = new Student("lucy", 15);
List<Student> students = new ArrayList<Student>();
students.add(student);
students.add(studenttwo);
String jsonString = JSONArray.toJSONString(students);



XML解析与序列化

在Android中,XML资源存储在assets或者res\xml或者res\raw目录中,我们在Eclipse构建Android项目是,xml及raw目录初始是未创建的,如果我们需要用到原始的xml资源,需要我们自己手动构建文件夹,并存储我们的资源到指定的(这里是raw或者xml)目录中。有了xml资源,我们在应用中就需要解析它,在Android中,常见的解析xml的方式有一下三种:SAX、Pull、Dom解析方式。

<!--用于解析的XML文件-->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <customer name="tom" age="20" gender="male" >
        <telphone>
            <phone>13636713128</phone>
        </telphone>
        <email>tom@yahoo.com</email>
    </customer>
    <customer name="kite" age="21" gender="male" >
        <telphone/>
        <email>kite@qq.com</email>
    </customer>
    <customer name="jeriffe" age="28" gender="male" >
        <telphone>
            <phone>13636713128</phone>
            <phone>13892008888</phone>
        </telphone>
       <email>jeriffe@126.com</email>
    </customer>
</resources>
//Java Bean
public class Person {
    private String name;
    private String sex;
    private int age;
    private String email;
    private List<String> phonesList;

    public Person() {
        phonesList = new ArrayList<String>();
    }

    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
    public List<String> getPhonesList() {
        return phonesList;
    }
    public void setPhonesList(List<String> phonesList) {
        this.phonesList = phonesList;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public void addPhone(String phoneNumber) {
        this.phonesList.add(phoneNumber);
    }
    @Override
    public String toString() {
        String phoneString = "";
        for (String phone : phonesList) {
            phoneString += "\n    " + phone;
        }
        return String.format("姓名:%s\n年龄:%d\n性别:%s\nEmail:%s\n电话:%s", name, age,sex, email, phoneString);
    }

}

Pull方式解析

Pull解析采用的是事件驱动的方式来解析XML文档,当我们开始解析后,我们可以通过调用XmlResourceParser.next()解析下一个解析事件(开始文档,结束文档,开始标签,结束标签)。当我们解析到某一个元素是我们可以通过XmlPullParser.getAttributte()方法来获取属性的值,也可调用它的XmlPullParser.nextText()获取本节点的值.

List<Person> resultsList = new ArrayList<Person>();
Person person = null;

Resources resources = getResources();
XmlResourceParser xrParser = resources.getXml(R.xml.customers);
try {
    while (xrParser.getEventType() != XmlResourceParser.END_DOCUMENT) {
        if (xrParser.getEventType() == XmlResourceParser.START_TAG) {
            String name = xrParser.getName();
            if (name.equals("customer")) {
                person = new Person();
                person.setName(xrParser.getAttributeValue(null, "name"));
                person.setAge(Integer.parseInt(xrParser
                        .getAttributeValue(1)));
                person.setSex(xrParser.getAttributeValue(2));

            } else if (name.equals("phone")) {
                person.addPhone(xrParser.nextText());
            } else if (name.equals("email")) {
                xrParser.next();
                person.setEmail(xrParser.getText());
            }
        } else if (xrParser.getEventType() == XmlPullParser.END_TAG) {
            String name = xrParser.getName();
            if (name.equals("customer")) {
                resultsList.add(person);
            }
        }

        xrParser.next();
    }
} catch (XmlPullParserException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

SAX解析

SAX即是:Simple API for XML。SAX解析也是一种基于事件驱动的API,有两个部分,解析器和事件处理器,解析器就是XMLReader接口,负责读取XML文档和向事件处理器发送事件(也是事件源),事件处理器接口,负责对发送的事件响应和进行XML文档处理。

//我们继承扩展的事件处理器
public class PersonSaxParserHandler extends DefaultHandler {

    class PersonConst {
        public static final int Persons = 1;
        public static final int Person_TELPHONE = 2;
        public static final int Person_PHONE = 3;
        public static final int Person_EMAIL = 4;

    }
    private List<Person> persons = new ArrayList<Person>();
    private Person person = null;
    private int currentState = 0;

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String theString = new String(ch, start, length);
        switch (currentState) {
            case PersonConst.Person_EMAIL :
                person.setEmail(theString);
                break;
            case PersonConst.Person_PHONE :
                person.addPhone(theString);
                break;
            default :
                break;
        }
        currentState=0;
    }
    @Override
    public void startDocument() throws SAXException {
        // 文档解析开始
        super.startDocument();
    }
    @Override
    public void endDocument() throws SAXException {
        // 文档解析开始
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {

        String node = localName.length() != 0 ? localName : qName;
        // 开始解析节点
        if (node.equals("customer")) {
            currentState = PersonConst.Persons;

            person = new Person();
            person.setName(attributes.getValue("name"));
            person.setAge(Integer.parseInt(attributes.getValue("age")));
            person.setSex(attributes.getValue("gender"));

            return;
        }
        
        if (node.equals("phone")) {
            currentState = PersonConst.Person_PHONE;
            return;
        }
        if (node.equals("email")) {
            currentState = PersonConst.Person_EMAIL;
            return;
        }
        
        currentState=0;
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // 解析节点结束
        if (localName.equals("customer")) {
            persons.add(person);
            return;
        }
    }

    public List<Person> getPersons() {
        return persons;
    }
}
//注:SAX解析的XML文件要存储在res\raw目录中,存储在res\xml目录中运行时报错。
// 1.构建一个工厂SAXParserFactory
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
// 2.构建并实例化SAXPraser对象
SAXParser saxParser = parserFactory.newSAXParser();
// 3.构建XMLReader解析器
XMLReader xmlReader = saxParser.getXMLReader();
// 4.这里是我们的具体类型的Handler对象
PersonSaxParserHandler parserHandler = new PersonSaxParserHandler();
// 5.解析器注册一个处理器
xmlReader.setContentHandler(parserHandler);
// 6.读取文件流
InputStream stream = getResources().openRawResource(R.raw.customers);
InputSource is = new InputSource(stream);
// 6.解析文件
xmlReader.parse(is);

List<Person> resList = parserHandler.getPersons();

DOM解析

DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大呢?手机CPU处理能力当然不能与PC机器比,因此在处理性能上会有折损。所以如果XML文件比较大,建议还是用上述的方式,而不用DOM方式。

//文件存储在assets目录下
// 构建一个DocumentBuilderFactory实例
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 构建DocumentBuilder
DocumentBuilder builder = factory.newDocumentBuilder();
// 读取文件流
AssetManager assetManager=getAssets();
InputStream stream=assetManager.open("customers.xml");
//InputStream stream = getResources().openRawResource(R.raw.customers);
// 得到代表整个xml的Document对象
Document document = builder.parse(stream);

// 遍历所有节点
Element root = document.getDocumentElement();
// 获取根节点的所有customer的节点
NodeList nodes = root.getElementsByTagName("customer");

for (int index = 0; index < nodes.getLength(); index++) {
    Person person = new Person();
    // 获取person元素节点
    Element personElement = (Element) (nodes.item(index));
    // 获取person中属性(Attributes)值
    person.setName(personElement.getAttribute("name"));
    person.setAge(Integer.parseInt(personElement.getAttribute("age")));
    person.setSex(personElement.getAttribute("gender"));

    // 获取telphone下标签
    Element telphoneElement = (Element) personElement
            .getElementsByTagName("telphone").item(0);
    NodeList phoneNodes = telphoneElement.getElementsByTagName("phone");
    for (int pIndex = 0; pIndex < phoneNodes.getLength(); pIndex++) {
        // 获取phone元素节点
        Element phoneElement = (Element) (phoneNodes.item(pIndex));
        person.addPhone(phoneElement.getFirstChild().getNodeValue());
    }
    // 获取email下标签
    Element emailElement = (Element) personElement
            .getElementsByTagName("email").item(0);
    person.setEmail(emailElement.getFirstChild().getNodeValue());

    resList.add(person);
}
posted on 2022-08-29 21:41  mt_procode  阅读(416)  评论(0)    收藏  举报