zoukankan      html  css  js  c++  java
  • 【C#】使用Json.NET(newtonsoft)解析Json

    最近做的WPF项目中,需要一个C#下的Json实现。
    在Json的官网http://www.json.org/中查找,可见C#的Json工具主要有如下:
    这里写图片描述
    尝试了排在最前面的fastJSON,反序列化时出了些问题,也没找到文档和案例,就改用了Json.NET。为啥用这个,因为在Visual Studio的NuGet中搜json时,出来的第一个就是它。。。
    (话说C#下的fastJSON由于其命名,某度上搜到的大多是阿里的Java实现https://github.com/alibaba/fastjson,蛋疼。。。)
    这里写图片描述

    做WPF桌面应用的客户端,数据由服务端以Json的形式传过来,所以先搞Json的反序列化,
    即 Json –> Object。

    关于工具Json.NET:

    现在假设收到的Json格式是下面这样的:

    [
        {
            "City": "南宁",
            "Community": [
                "南宁A小区",
                "南宁B小区",
                "南宁C小区"
            ]
        },
        {
            "City": "柳州",
            "Community": [
                "柳州A小区",
                "柳州B小区",
                "柳州C小区"
            ]
        },
        {
            "City": "桂林",
            "Community": [
                "桂林A小区",
                "桂林B小区",
                "桂林C小区"
            ]
        }
    ]

    现在,根据文档中的这个案例:

    http://www.newtonsoft.com/json/help/html/ReadJsonWithJsonTextReader.htm

    string json = @"{
        'CPU': 'Intel',
        'PSU': '500W',
        'Drives': [
          'DVD read/writer'
          /*(broken)*/,
          '500 gigabyte hard drive',
          '200 gigabype hard drive'
        ]
    }";
    
    JsonTextReader reader = new JsonTextReader(new StringReader(json));
    while (reader.Read())
    {
        if (reader.Value != null)
        {
            Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value);
        }
        else
        {
            Console.WriteLine("Token: {0}", reader.TokenType);
        }
    }
    
    // Token: StartObject
    // Token: PropertyName, Value: CPU
    // Token: String, Value: Intel
    // Token: PropertyName, Value: PSU
    // Token: String, Value: 500W
    // Token: PropertyName, Value: Drives
    // Token: StartArray
    // Token: String, Value: DVD read/writer
    // Token: Comment, Value: (broken)
    // Token: String, Value: 500 gigabyte hard drive
    // Token: String, Value: 200 gigabype hard drive
    // Token: EndArray
    // Token: EndObject

    思路:使用JsonTextReader类,判断reader.TokenType和reader.Value来解析并处理。

    首先根据Json数据,构建一个C#的数据类。

    CityAndCommunity.cs:

    class CityAndCommunity
    {
        public string City { get; set; }
        public string[] Community { get; set; }
    
        public override string ToString()
        {
            if (Community != null)
            {
                string communityStr = "";
                for (int i = 0; i < Community.Length; i++)
                {
                    if (i != Community.Length - 1)
                    {
                        communityStr += Community[i] + " , ";
                    }
                    else
                    {
                        communityStr += Community[i].ToString();
                    }
                }
                return "==============================
     City = "
                    + City + " , communityStr = " + communityStr
                    + "
     ======================================";
            }
            return base.ToString();
        }
    }

    对应的解析方法:

    class SystemUtils
    {
        /// <summary>
        /// Json --> Object
        /// </summary>
        public static void GetCityAndCommunityStringData()
        {
            string json = SystemUtils.GetJsonString(); // 获取到Json字符串
    
            List<CityAndCommunity> list = new List<CityAndCommunity>();
            List<string> communitiesList = new List<string>(); // 用于存一个城市里的多个小区,最后转成字符数组string[]
            CityAndCommunity obj = null;
            bool isCommunity = false; // 用于判断读到的是否为数组内容,否则是城市名!
    
            System.Console.WriteLine("------------------------------");
            JsonTextReader reader = new JsonTextReader(new StringReader(json));
            while (reader.Read())
            {
                if (reader.Value != null) // 有内容
                {
                    // Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value);
    
                    if (reader.TokenType == JsonToken.String)
                    {
                        if (isCommunity)
                        {
                            // 是社区组
                            communitiesList.Add(reader.Value.ToString());
                        }
                        else
                        {
                            // 是城市名
                            obj.City = reader.Value.ToString();
                        }
                    }
                }
                else
                {
                    // Console.WriteLine("Token: {0}", reader.TokenType);
                    if (reader.TokenType == JsonToken.StartObject)
                    {
                        isCommunity = false;
                        obj = new CityAndCommunity();
                    }
                    else if (reader.TokenType == JsonToken.StartArray)
                    {
                        // Json从开始到第一个对象开始,连续有两个[开始符号,但这里无所谓,可以不用flag分开处理
                        communitiesList = new List<string>();
                        isCommunity = true;
                    }
                    else if (reader.TokenType == JsonToken.EndArray)
                    {
                        if (communitiesList != null) // Json从最后一个对象结束到整个字符串的结束,连续有两个]结束符
                        {
                            obj.Community = communitiesList.ToArray();
                            communitiesList = null;
                            isCommunity = false;
                        }
                    }
                    else if (reader.TokenType == JsonToken.EndObject)
                    {
                        list.Add(obj);
                        obj = null;
                    }
                }
            }
            System.Console.WriteLine("------------------------------");
            System.Console.WriteLine("list.Count = " + list.Count);
            System.Console.WriteLine("------------------------------");
            for (int i = 0; i < list.Count; i++)
            {
                System.Console.WriteLine(list[i].ToString());
            }
    
        }
    }

    运行后打印结果如下:

    ------------------------------
    Token: StartArray
    Token: StartObject
    Token: PropertyName, Value: City
    Token: String, Value: 南宁
    Token: PropertyName, Value: Community
    Token: StartArray
    Token: String, Value: 南宁A小区
    Token: String, Value: 南宁B小区
    Token: String, Value: 南宁C小区
    Token: EndArray
    Token: EndObject
    Token: StartObject
    Token: PropertyName, Value: City
    Token: String, Value: 柳州
    Token: PropertyName, Value: Community
    Token: StartArray
    Token: String, Value: 柳州A小区
    Token: String, Value: 柳州B小区
    Token: String, Value: 柳州C小区
    Token: EndArray
    Token: EndObject
    Token: StartObject
    Token: PropertyName, Value: City
    Token: String, Value: 桂林
    Token: PropertyName, Value: Community
    Token: StartArray
    Token: String, Value: 桂林A小区
    Token: String, Value: 桂林B小区
    Token: String, Value: 桂林C小区
    Token: EndArray
    Token: EndObject
    Token: EndArray
    ------------------------------
    list.Count = 3
    ------------------------------
    ==============================
     City = 南宁 , communityStr = 南宁A小区 , 南宁B小区 , 南宁C小区
     ======================================
    ==============================
     City = 柳州 , communityStr = 柳州A小区 , 柳州B小区 , 柳州C小区
     ======================================
    ==============================
     City = 桂林 , communityStr = 桂林A小区 , 桂林B小区 , 桂林C小区
     ======================================

    注意:以上解析方法是通过对照着打印Json的解析结果来写的,所以不具有通用性!
    为了便于理解,Json格式和解析结果的对应关系如下:
    这里写图片描述


    一些其他参考:

    http://blog.csdn.net/coolszy/article/details/8606803
    http://blog.csdn.net/joyhen/article/details/24805899



    2016.12.6傍晚 重要更新:

    我发现自己就特么是个大写的SB啊!!!!!

    看Json.NET文档看到了下面这个例子:
    http://www.newtonsoft.com/json/help/html/DeserializeObject.htm
    顺便截个图:
    这里写图片描述

    从例子可以看出,Json.NET已经实现了属性自动映射!!!
    根据测试,映射规则是:

    • 类中的属性名与Json中的Key值相同。
    • 大小写不敏感。
    • 属性的先后顺序无关。

    对于当前的需求,可以参考反序列化Dictionary类的例子:
    这里写图片描述

    所以代码可以简化为:

    class SystemUtils
    {
        /// <summary>
        /// Json --> Object
        /// </summary>
        public static void GetCityAndCommunityStringData()
        {
            string json = SystemUtils.GetJsonString(); // 获取到Json字符串
    
            new list<CityAndCommunity> = JsonConvert.DeserializeObject<List<CityAndCommunity>>(json);
    
            System.Console.WriteLine("------------------------------");
            System.Console.WriteLine("城市数量:list.Count = " + list.Count);
            System.Console.WriteLine("------------------------------");
            for (int i = 0; i < list.Count; i++)
            {
                System.Console.WriteLine(list[i].ToString());
            }
        }
    }

    运行结果如下:

    ------------------------------
    list.Count = 3
    ------------------------------
    ==============================
     City = 南宁 , communityStr = 南宁A小区 , 南宁B小区 , 南宁C小区
     ======================================
    ==============================
     City = 柳州 , communityStr = 柳州A小区 , 柳州B小区 , 柳州C小区
     ======================================
    ==============================
     City = 桂林 , communityStr = 桂林A小区 , 桂林B小区 , 桂林C小区
     ======================================

    总结:Json.NET已经实现了属性自动映射,很强大很好用。最上面写的那一大坨垃圾代码也留在这篇博客中吧,就当作是记录下学习的过程。 ( ´_ゝ`)

  • 相关阅读:
    hdu 4114 Disney's FastPass 状压dp
    lightoj 1381
    bzoj 2428: [HAOI2006]均分数据 随机化
    bzoj 3969: [WF2013]Low Power 二分
    套题:wf2013 (1/8)
    hdu 4119 Isabella's Message 模拟题
    hdu 4118 Holiday's Accommodation 树形dp
    UESTC 2015dp专题 N 导弹拦截 dp
    UESTC 2015dp专题 j 男神的约会 bfs
    UESTC 2015dp专题 H 邱老师选妹子 数位dp
  • 原文地址:https://www.cnblogs.com/guxin/p/csharp-parse-json-by-newtonsoft-json-net.html
Copyright © 2011-2022 走看看