JSON 与 XML 的区别、优劣势对比
1. 理解由来
IO:数据移动
数的意义如何来解决?
2.properties
属性:属性名与属性值,
properties属性
储存方式:key=value
(键值对)
作用:定义一个变量,在这个文件里面定义这些变量的值,在程序里面可以调用这些变量,好处就是,如果程序中的参数值需要变动,直接来改这个.property文件就可以了,不用在去修改源代码。
3.JSON
JSON三种常用解析方式:fastjson
json
jackson
JSON是一种传递对象的语法
如:
单对象:{key:value}
多对象: [{},{},...]
嵌套对象:
{
key:[
{
key:value,
key:{
key:value
}
}
]
}
通过学习json
map = java 普通类 类似
3.1、meven架包
都是用于用于解析json文件gson
和fastjson
用法一样
fastjson(阿里)
实现json对象与json字符串的转换
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.11</version>
</dependency>
gson(谷歌)
实现json对象与json字符串的转换
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
3.2、泛型嵌套问题
泛型嵌套 要获取 里面 泛型的内容用TypeToken()
但在jdk10以后删除了TypeToken()
所以用 new ParameterizedTypeImpl()
Map<String, List<Student>> map = gson.fromJson(json, new ParameterizedTypeImpl(new Type[]{
String.class,
new ParameterizedTypeImpl(new Type[]{String.class},null,List.class)
},null,Map.class));
4.xml
全名:eXtensible Markup Language
翻译:可扩展标记语言
XPath语法学习网站:
XPath 语法 | 菜鸟教程
作用:
1.配置 (保存数据)
2.数据交互(获取第三方数据)
<student id="1">
<name>zhangsan</name>
<age>17</age>
</student>
<student id="2">
<name>lizi</name>
<age>18</age>
</student>
定义 用于验证:schema
是一个xml DTD
是一个文本
4.1、xml解析
两类:树形解析(DOM)和 流事件解析(SAX)
树形解析(DOM)
优点:由于整棵树在内存中,因此可以对XML文档随机访问;可以对XML文档进行修改操作;
缺点:整个文档必须一次性解析完;由于整个文档都需要载入内存,对于大文档成本高;
Node
类型主要的有Element
Arrt
Test
流事件解析(SAX)
优点:解析速度快,占用内存少,它需要哪些数据再加载和解析哪些内容。
缺点:它不会记录标签的关系,而是需要应用程序自己处理,这样就会增加程序的负担。
特殊字符在xml中表示的两种方式:
1.使用实体码 &xxx;
例如:< <
> >
2.使用<![CDATA[]]> <info><![CDATA[xml里面的标签这么定于:<student>zhang san</<student>]]></info>
4.2、meven架包
都用于解析xml
xml-apis
提供了一组 Apache 托管的 DOM、SAX 和 JAXP 接口,用于其他基于 xml 的项目
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
</dependency>
dom4j
用于 Java 的灵活 XML 框架
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
jaxen
Jaxen 是一个用 Java 编写的开源 XPath 库。它适用于许多不同的对象模型,包括 DOM、XOM、dom4j 和 JDOM。
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
5.dom4j
dom4j
是开源的xml解析包 支持 DOM,SAX 和 JAXP。
自学XPath
XPath是对 xml 文档随机查询的一种技术
XPath介绍doc.selectNodes("//name")
学习XPath语法规则
6.json案例
6.1、解析json
name:student.json
ba=com.bigdata.demo.Ba
ti=com.bigdata.demo.Ti
ds=com.bigdata.demo.RiQiDanShuang
public class Test {
static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws Exception{
//写入配置文件
Properties pros = new Properties();
pros.load(new FileInputStream("src/main/resources/config.properties"));
System.out.println("输入消费总金额");
double zong=Double.parseDouble(input.nextLine());
//实现打折代码
System.out.println("请输入打折类名:");
String name = input.nextLine();
//pros.getProperty(name)获取类路径
//DaZheFactory.newInstance()转换类路径写入父类方法中
DaZhe daZhe=DaZheFactory.newInstance(pros.getProperty(name));
double zehou = daZhe.zhe(zong);
System.out.println("总金额为"+zong);
System.out.println("折后金额为"+zehou);
System.out.println("本次消费为您节省了"+(zong-zehou));
}
}
public class DaZheFactory {
public static DaZhe newInstance(String name) throws Exception{
//反射
Class<DaZhe> daZheClass= (Class<DaZhe>) Class.forName(name);
return daZheClass.newInstance();
}
}
public interface DaZhe {
double zhe(double zong);
}
public class Ba implements DaZhe{
@Override
public double zhe(double zong) {
return zong*0.8;
}
}
public class RiQiDanShuang implements DaZhe{
@Override
public double zhe(double zong) {
Date date=new Date();
SimpleDateFormat df=new SimpleDateFormat("dd");
int day = Integer.parseInt(df.format(date));
if (day%2==0){
return zong*0.7;
}
return zong*0.8;
}
}
public class Ti implements DaZhe{
@Override
public double zhe(double zong) {
//多重if
if (zong<=100){
return zong*0.9;
}
if (zong<=300){
return zong*0.8;
}
if (zong<=500){
return zong*0.7;
}
if (zong<=1000){
return zong*0.6;
}
return zong*0.5;
}
}
6.2、fasjson 解析 json
name:student.json
{
"name": "张三",
"age": 19
}
name:students.json
[
{
"name": "张三",
"age": 17
},
{
"name": "李四",
"age": 19
},
{
"name": "王五",
"age": 18
}
]
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) throws Exception{
/*String json="{\n" +
" \"name\": \"张三\",\n" +
" \"age\": 19\n" +
"}";*/
InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("student.json");
Student student = JSONObject.parseObject(resourceAsStream, Student.class);
System.out.println(student);
System.out.println(student.getName());
}
}
public class Test2 {
public static void main(String[] args) throws Exception{
InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("students.json");
BufferedReader reader=new BufferedReader(new InputStreamReader(resourceAsStream));
StringBuilder sb=new StringBuilder();
while (true){
String line=reader.readLine();
if (line == null) {
break;
}
sb.append(line);
}
String json=sb.toString();
List<Student> students = JSONArray.parseArray(json, Student.class);
int sum=0;
for (Student s:students
) {
System.out.println(s);
sum+=s.getAge();
}
System.out.println("平均年龄为:"+(sum/students.size()));
}
}
public class Test3 {
public static void main(String[] args) throws Exception{
//通过 流 获取json文件中的内容
InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("muitlClassStudents.json");
//把内容转换 放入 BufferedReader
BufferedReader reader=new BufferedReader(new InputStreamReader(resourceAsStream));
//把内容 拼接 到StringBuilder
StringBuilder sb=new StringBuilder();
while (true){
String line=reader.readLine();
if (line == null) {
break;
}
sb.append(line);
}
String json=sb.toString();
//fasjson 解析 json
Map<String, List<Student>> map= JSONObject.parseObject(json,Map.class);
//获取map的key值并储存
Set<String> bans=map.keySet();
System.out.println("共有"+bans.size());
for (String s:bans
) {
System.out.println(s);
System.out.println(s+"有"+map.get(s).size());
}
//java对象转化为 json 字符串对象
System.out.println(JSONObject.toJSON(map));
}
}
6.3、gson 解析 json
TypeToken()
11jdk 不存在
name:muitlClassStudents.json
{
"08班":[
{
"name": "张三",
"age": 17
},
{
"name": "李四",
"age": 19
},
{
"name": "王五",
"age": 18
}
],
"09班": [
{
"name": "ttt",
"age": 19
},
{
"name": "eee",
"age": 18
}
],
"10班": [
{
"name": "abc",
"age": 11
}
]
}
public class Test {
public static void main(String[] args) throws Exception {
InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("muitlClassStudents.json");
BufferedReader reader=new BufferedReader(new InputStreamReader(resourceAsStream));
StringBuilder sb=new StringBuilder();
while (true){
String line=reader.readLine();
if (line == null) {
break;
}
sb.append(line);
}
String json=sb.toString();
//gson解析
Gson gson=new Gson();
//输出班级学生的方法 TypeToken() JDK10之后不可用所以自己写 ParameterizedType()
Map<String, List<Student>> map = gson.fromJson(json, new ParameterizedTypeImpl(new Type[]{
String.class,
new ParameterizedTypeImpl(new Type[]{String.class},null,List.class)
},null,Map.class));
//相当于下面
/*Map<String, List<Student>> map = gson.fromJson(json, new ParameterizedType(){
@Override
public Type[] getActualTypeArguments() {
//返回 泛型参数类型
return new Type[]{
String.class,
new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[]{
Student.class
};
}
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
}
};
}
@Override
public Type getRawType() {
//返回 泛型类型本身
return Map.class;
}
@Override
public Type getOwnerType() {
return null;
}
});*/
Set<String> bans=map.keySet();
System.out.println("共有"+bans.size());
//输出全部班级
System.out.println(JSONObject.toJSON(bans));
for (String s:bans
) {
System.out.println(s);
System.out.println(s+"有"+map.get(s).size());
//输出班级全部学生
List<Student> student = map.get(s);
for (Student stu:student
) {
System.out.print(stu.getName()+" ");
}
System.out.println();
}
}
}
7、xml案例
7.1、解析xml
<?xml version="1.0" encoding="UTF-8" ?>
<student id="1" falg="false">
<name>zhangsan</name>
<age>18</age>
<info><![CDATA[xml里面的标签这么定于:<student>zhang san</<student>]]></info>
</student>
public class Student {
private String name;
private int age;
private String info;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", info='" + info + '\'' +
", id=" + id +
'}';
}
public Student(String name, int age, String info, int id) {
this.name = name;
this.age = age;
this.info = info;
this.id = id;
}
public Student() {
}
}
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws Exception{
//创建工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder db = dbf.newDocumentBuilder();
//通过流 移动获取数据
InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("student.xml");
//解析文档 通过 构建 创建 document 对象(DOM)
Document parse = db.parse(resourceAsStream);//解析完成,生成了一颗树
System.out.println(parse);
//Element 是一个 接口,描述了 <student> 这个东西
Element root=parse.getDocumentElement();
System.out.println(root);
NodeList childNodes = root.getChildNodes();
Student student=new Student();
// 获取根节点的属性id
String id = root.getAttribute("id");
// 获得所有的属性 没有父接口不能用foreach循环
NamedNodeMap attributes = root.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node item = attributes.item(i);
Attr item1 = (Attr) item;
// getValue() : 是Attr属性中独有的方法 获取文本内容
System.out.println(item1.getValue());
// getTextContent() : 获得文本内容
//System.out.println(item.getTextContent());
}
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
// 判断孩子的类型
if (item.getNodeType()==Node.ELEMENT_NODE){
System.out.println(item);
System.out.println(item.getTextContent());
if (item.getNodeName().equals("name")){
student.setName(item.getTextContent());
}
if (item.getNodeName().equals("age")){
student.setAge(Integer.parseInt(item.getTextContent()));
}
if (item.getNodeName().equals("info")){
student.setInfo(item.getTextContent());
}
}
}
System.out.println(student);
}
}
7.2、xml树形解析
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1" falg="false">
<name>zhangsan</name>
<age>17</age>
<info><![CDATA[xml里面的标签这么定于:<student>zhang san</<student>]]></info>
</student>
<student id="2">
<name>lisi</name>
<age>18</age>
<info><![CDATA[xml里面的标签这么定于:<student>zhang san</<student>]]></info>
</student>
<student id="3">
<name>wangwu</name>
<age>19</age>
<info><![CDATA[xml里面的标签这么定于:<student>zhang san</<student>]]></info>
</student>
</students>
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) throws Exception{
//创建工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder db = dbf.newDocumentBuilder();
//通过流移动数据,获取数据
InputStream in = com.bigdata.demo.Test.class.getClassLoader().getResourceAsStream("students.xml");
//解析文档
Document doc=db.parse(in);
//定义容器存放student数据
ArrayList<Student> students = new ArrayList<>();
//通过文档获取根节点然后利用根节点查找根节点下的所有student标签对象
NodeList elements = doc.getDocumentElement().getElementsByTagName("student");
//遍历
for (int i = 0; i < elements.getLength(); i++) {
//获取每一个Student标签元素
Element element= (Element) elements.item(i);
//Student 元素上有一个Id属性 获取他,获取的数据类型String要求是int
int id= Integer.parseInt(element.getAttribute("id"));
//获取当前student元素下所有叫name的元素
String name=element.getElementsByTagName("name").item(0).getTextContent();
String info=element.getElementsByTagName("info").item(0).getTextContent();
//连续.的是匿名变量(只能用一次)
int age= Integer.parseInt(element.getElementsByTagName("age").item(0).getTextContent());
//创建java中的student对象
Student student = new Student(name, age, info, id);
//添加到student集合中
students.add(student);
}
for (Student s:students
) {
System.out.println(s);
}
}
}
7.3、流事件解析
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception{
//创建SAXParser解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
//构建解析器
SAXParser parser = spf.newSAXParser();
InputStream in = com.bigdata.demo.Test.class.getClassLoader().getResourceAsStream("students.xml");
MyHandeler myHandeler = new MyHandeler();
//解析 使用到了自定义事件处理器
parser.parse(in,myHandeler);
for (Student s:myHandeler.getList()
) {
System.out.println(s);
}
}
}
/*
*通过继承默认的事件处理器 重写事件处理方法 完成关心数据的提取
* */
class MyHandeler extends DefaultHandler{
//解析提取数据存放的容器
private List<Student> list=new ArrayList<>();
//在各个解析事件中共享的student对象
private Student stu;
//始终记录 当前正在执行的标签名
private String cQ;//currentQname
//获取解析结果的方法
public List<Student> getList() {
return list;
}
@Override
public void startDocument() throws SAXException {
System.out.println("开始解析");
}
@Override
public void endDocument() throws SAXException {
System.out.println("完成解析");
}
/**
* 元素开始 student name age info
* @param uri
* @param localName
* @param qName
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println(qName+"开始解析");
//一旦开始解析student对象
if ("student".equals(qName)){
//新建一个student
this.stu=new Student();
//获取id属性
String id = attributes.getValue("id");
this.stu.setId(Integer.parseInt(id));
list.add(this.stu);
}
//实时获取标签名
this.cQ=qName;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println(qName+"开始解析完成");
if ("student".equals(this.cQ)&&"student".equals(qName)){
this.stu=null;
}
this.cQ=null;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//通过字符数组创建字符串对象
String s = new String(ch, start, length);
System.out.println("解析到"+s);
if ("name".equals(this.cQ)){
this.stu.setName(s);
}
if ("age".equals(this.cQ)){
this.stu.setAge(Integer.parseInt(s));
}
if ("info".equals(this.cQ)){
this.stu.setInfo(s);
}
}
}
dom4j解析
pom.xml
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
复制import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) throws Exception{
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(Test.class.getClassLoader().getResourceAsStream("students.xml"));
Element rootElement = doc.getRootElement();
System.out.println(rootElement);
Iterator<Element> student = rootElement.elementIterator("student");
ArrayList<Student> datas=new ArrayList<>();
while (student.hasNext()){
Element element = student.next();
System.out.println(element);
int id= Integer.parseInt(element.attributeValue("id"));
String name=element.elementText("name");
String info=element.elementText("info");
int age= Integer.parseInt(element.elementText("age"));
datas.add(new Student(name,age,info,id));
}
for (Student s:datas
) {
System.out.println(s);
}
//XPath对 xml文档随机查询的解决方案
for (Node n:doc.selectNodes("//name")
) {
System.out.println(n.getText());
}
}
}