大纲
程序 = 数据结构 + 算法,可以理解成,程序 = 变量 + 方法;方法就像一个黑盒,变量流入黑盒,经过方法加工再流出。
所以,程序是由众多变量和方法构成的,那怎么组织这些繁杂的变量和方法呢?
面向对象的编程语言,变量也被封装进一个个的类中,此时,可以把类看作是一个数据包而已,静态变量和实例变量不同;通过【new 数据包】构造一个全新的数据包,从而在整个应用程序中,实例变量可以有很多份;静态变量只有一份。将方法分门别类放到各个类中组织起来,静态方法和实例方法没什么区别,都是被圈禁在类中的方法。只是静态方法只能流入静态变量,实例方法可以流入静态或实例变量。
数据存储在数据库,相当于存储在仓库;数据存储在磁盘,相当于存储在背包;数据存储在变量,相当于拿在手里。一份数据不管存储在哪里,在提供给方法使用时,是完全等价,表示完全相同的意义。有一种特殊格式的数据,可以放进数据库,磁盘,内存(被类组织起来的变量,相当于数据包)中,三个地方的表示方法不同,但是相互映射,完全等价,这种格式就叫Json。
类是一种数据包,能够封装不同类型的数据,数组也是一种数据包,能够封装相同类型的数据。
Json是一种基于字面值的对象表示法,是一种数据交换格式。
Json是文本,可以描述一个类,可以存储在磁盘,放在磁盘可以记录状态,可持续化,在需要的时候转换成内存中的对象使用。
C++ 和 C#是两种不同的语言,二者的数据类型不同。Json有6种数据类型【数字】【字符串】【布尔】【null】【对象】【数组】,Json是中介,C++可以将Json的类型解读成自己的类型,或者将自己的类型解析成Json类型,C#同样可以,这样,C++和C#就可以交互数据了。这如同日本人和中国人通过英文相互交流,中国人将汉语转换成英文对日本人说,日本人听到英文,将英文翻译成日文,然后理解了中国人说了什么,反之亦然。
什么叫字面量(literal)?5就是5,称为字面量。x = 5,x是变量,不是字面量。
Json的数字,字符串,布尔,null都是字面值,字面值再组成数组和对象。对象是不同类型的数据的集合,数组是相同类型的数据的集合。再复杂的数据类型拆开后,都是由字面量组成的。
json表示对象时,属性名(key)必须用双引号包裹,对于Json而言,key名可以包含空格,#,%等字符串,但是为了兼容更多的语言,尽量不要使用特殊字符,数字字母下划线最好,。 value如果是字符串类型,可以是任何形式任何字符。value并不需要总被双引号包裹,value是字符串时,必须使用双引号。如果是数字,布尔值,数组,对象,null,这些都不应被双引号包裹。
json的媒体类型是application/json
Json中字符串
json中的字符串类型必须用双引号包裹,不能是单引号。
字符串中含有双引号怎么办?
"promo" : " "hello world" " 这种表示是错的
"promo" : " "hello world" "
字符串中含有\怎么办?
"location" : "C:\program files"
"location" : "C:\program files"
除了双引号和反斜线,还需要转义的字符
\b 退格符
\f 换页符
\t 制表符
\n 换行符
\r 回车符
\u后面跟十六进制字符 (\u263A)
Json中的数字
Json中的布尔
在json中布尔字面值必须是小写的,如"true" "false"。
Json中的null
null表示一个没有值的值,必须是小写。
Json中的数组
["str1","str2",null, 5.0] 这种表示对于json是合法的,但是我们应该尽量避免这样做,因为这种json数组可以被动态语言正确解析成列表数据类型,但是像C#,java,C++这种强类型语言无法解析成泛型数组或泛型列表数据类型。
三种系统描述同一种数据结构
Json是基于字面值的对象表示法的数据格式,有以下类型:
- 数字(1)
- 字符串("str")
- 布尔(true false)
- null(null)
- 数组[e1,e2]
- 对象{"p1":1,"p2":"ok","p3":[e1,e2]}
Linq to Json的类型有:
- 数字(new JValue(1))
- 字符串(new JValue("str"))
- 布尔(new JValue(true))
- null(JValue.CreateNull)
- JArray
- JObject
但是Linq to Json也提供一个JToken类型,它是JArray, JObject,JValue的基类,可以表示6个类型的任何一个。
.NET类型有:
- 数字(1)
- 字符串("str") DateTime TimeSpan Uri GUID 枚举
- 布尔(true)
- null(null)
- 线性列表容器(IList
- class Dictionary<TKey,TValue> DataSet
C# <=> Json <=> C++
C#和C++实现类型映射,是通过Json实现的。C#的某个类型Acsharp映射成Json的某个类型Ajson,如果C++的某个类型Acpp也映射成Json的类型Ajson,那么C#的类型Acsharp和C++的类型Acpp就实现了映射。Json共有6种类型,每种类型可以映射C#语言的多种类型,只要高级语言的类型可以映射成Json的某个类型,那高级语言的这个类型就可以和Json序列化和反序列化。
Json的数组的元素可以是不同类型,Linq to Json的JArray也可以容纳不同类型,.NET的线性列表类型如果是ArrayList可以映射Json和Linq to Json中元素类型不同的数组,如果是泛型的IList
.NET Type,Json,Linq to Json是独立又相互映射,核心思想是C++类型和C#类型通过Json为中介实现相互映射,可以通信。
用三种系统构建同一种数据结构时,各系统只能使用各自系统的类型进行增删改。
已知一种系统,能够快速构建完全等价的其他两种系统
1. Linq to Json <=> Json
利用Linq to Json快速构造指定的Json
指定的Json
{
"MyArray": [
1,
false,
null,
[],
"Manual text",
"2020-09-11T21:23:10.4145426+08:00",
"00:00:00.0000010",
"C:\\\\d.txt"
]
}
方法一:Linq 2 Json的无参构造方法
JArray arr = new JArray();
arr.Add(new JValue(1));
arr.Add(new JValue(false));
arr.Add(JValue.CreateNull());
arr.Add(new JArray());
arr.Add(new JValue("Manual text"));
arr.Add(new JValue(DateTime.Now));
arr.Add(new JValue(new TimeSpan(10)));
arr.Add(new JValue(new Uri(@"C:\\d.txt")));
JObject obj = new JObject();
obj["MyArray"] = arr;
方法二:Linq to Json的构造方法的初始化器
JObject obj = new JObject()
{
"MyArray",new JArray()
{
new JValue("Manual text"),
new JValue(DateTime.Now),
new JValue(1),
new JValue(false),
new JValue(new TimeSpan(10)),
new JValue(new Uri(@"C:\\d.txt")),
JValue.CreateNull(),
new JArray()
}
};
方法三: 利用JProperty
JObject obj = new JObject();
obj.Add
(
new JProperty("MyArray",
new JArray() {
new JValue("Manual text"),
new JValue(DateTime.Now),
new JValue(1), new JValue(true),
JValue.CreateNull(),
new JValue(new TimeSpan(10)),
new JValue(new Uri(@"C:\\d.txt")),
new JArray()
})
);
Linq to Json转换成Json
new JArray().ToString();
new JObject().ToString();
new JValue(1.0).ToString();
new JValue("str").ToString();
new JValue(true).ToString();
JValue.CreateNull().ToString();
利用Json快速构造指定的Linq to Json
Json转换成Linq to Json
string json = @"[
""Small"",
""Medium"",
""Large""
]";
JArray arr = JArray.Parse(json);
JToken token = JToken.Parse(json);
json = @"{
CPU: 'Intel',
Drives: [
'DVD read/writer',
'500 gigabyte hard drive'
]
}";
JObject obj = JObject.Parse(json);
token = JToken.Parse(json);
json = "1";
JValue value = JToken.Parse(json) as JValue;
json = "\"1\"";
value = JToken.Parse(json) as JValue;
json = "\"1\"";
value = JToken.Parse(json) as JValue;
json = "true";
value = JToken.Parse(json) as JValue;
json = "null";
value = JToken.Parse(json) as JValue;
得知每个Token的实际类型,JValue的实际类型. 递归遍历输出一个对象所有的基本类型的类型和值。
2. DotNET Type <=> Json
利用DotNET Type快速构造Json
指定的Json
[{"UserName":"test","Address":"gz"}]
方式一:采用匿名类型比较快速简洁
JsonConvert.SerializeObject(new ArrayList() { new
{
UserName = "test",
Address = "gz"
}});
方式二:
class Person
{
public string UserName { get; set; }
public string Address { get; set; }
}
JsonConvert.SerializeObject(new List<Person>() { new Person() { UserName = "test", Address = "gz"} });
DotNET Type转换成Json
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
JsonConvert.SerializeObject(account, Formatting.Indented);
JsonConvert.SerializeObject(new List<Person>() { new Person() { UserName = "test", Address = "gz"} });
JsonConvert.SerializeObject(new Person() { UserName = "test", Address = "gz" });
JsonConvert.SerializeObject(1);
JsonConvert.SerializeObject(false);
JsonConvert.SerializeObject(null);
JsonConvert.SerializeObject("str");
JsonConvert.SerializeObject(DateTime.Now);
JsonConvert.SerializeObject(Guid.NewGuid());
JsonConvert.SerializeObject(new Uri("C:\\test.txt", UriKind.Absolute));
newtonsoft.json特殊处理过.NET的字典,它映射Json中的对象类型。DataSet也是同样。//TODO
字典序列化时,每个key的ToString()字符串作为属性名称,每个属性的值是字典的Value映射的Json类型。
Dictionary<Person, int> dic = new Dictionary<Person, int>();
dic[new Person() { UserName = "A", Address = "a" }] = 1;
dic[new Person() { UserName = "B", Address = "b" }] = 2;
JsonConvert.SerializeObject(dic);
利用Json快速构造DotNET Type
Json转换成DotNET Type
JsonConvert.DeserializeObject<int>("1");
JsonConvert.DeserializeObject<string>("\"str\"");
JsonConvert.DeserializeObject<bool>("false");
JsonConvert.DeserializeObject<ArrayList>("[]");
JsonConvert.DeserializeObject<object>("{}");
JsonConvert.DeserializeObject<Dictionary<string,int>>(@"{'A':1,'B':2}");
JsonConvert.DeserializeObject<Guid>("\"970a0dff-de1d-45da-9000-6d7c5c00f53f\"");
JsonConvert.DeserializeObject<Uri>(@"""C:\\test.txt""");
JsonConvert.DeserializeObject<Person>(@"{'UserName':'Danqing Zhu','Address':'周口 河南' }");
简洁方法
var definition = new { Name = "" };
string json1 = @"{'Name':'James'}";
var customer1 = JsonConvert.DeserializeAnonymousType(json1, definition);
Console.WriteLine(customer1.Name);
// James
string json2 = @"{'Name':'Mike'}";
var customer2 = JsonConvert.DeserializeAnonymousType(json2, definition);
Console.WriteLine(customer2.Name);
// Mike
3. Linq to Json <=> DotNET Type
利用Linq to Json快速构造DotNET Type
Linq to Json转换成DotNET Type
JObject.FromObject(new object());
JArray.FromObject(new List<string>());
JToken.FromObject(1);