newtonsoft.json

大纲

newtonsoft.json

程序 = 数据结构 + 算法,可以理解成,程序 = 变量 + 方法;方法就像一个黑盒,变量流入黑盒,经过方法加工再流出。

所以,程序是由众多变量和方法构成的,那怎么组织这些繁杂的变量和方法呢?

面向对象的编程语言,变量也被封装进一个个的类中,此时,可以把类看作是一个数据包而已,静态变量和实例变量不同;通过【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)

newtonsoft.json

Json中的数字

newtonsoft.json

Json中的布尔

在json中布尔字面值必须是小写的,如"true" "false"。

Json中的null

null表示一个没有值的值,必须是小写。

Json中的数组

["str1","str2",null, 5.0] 这种表示对于json是合法的,但是我们应该尽量避免这样做,因为这种json数组可以被动态语言正确解析成列表数据类型,但是像C#,java,C++这种强类型语言无法解析成泛型数组或泛型列表数据类型。

三种系统描述同一种数据结构

Json是基于字面值的对象表示法的数据格式,有以下类型:

  1. 数字(1)
  2. 字符串("str")
  3. 布尔(true false)
  4. null(null)
  5. 数组[e1,e2]
  6. 对象{"p1":1,"p2":"ok","p3":[e1,e2]}

Linq to Json的类型有:

  1. 数字(new JValue(1))
  2. 字符串(new JValue("str"))
  3. 布尔(new JValue(true))
  4. null(JValue.CreateNull)
  5. JArray
  6. JObject

但是Linq to Json也提供一个JToken类型,它是JArray, JObject,JValue的基类,可以表示6个类型的任何一个。

.NET类型有:

  1. 数字(1)
  2. 字符串("str") DateTime TimeSpan Uri GUID 枚举
  3. 布尔(true)
  4. null(null)
  5. 线性列表容器(IList
  6. class Dictionary<TKey,TValue> DataSet

C# <=> Json <=> C++

newtonsoft.json

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);

利用DotNET Type快速构造Linq to Json

DotNET Type转换成Linq to Json

上一篇:newtonsoft


下一篇:C# Newtonsoft.Json解析json字符串处理 - JToken 用法