【C#】JSON to Nested Dictionary,巢狀JSON轉Dictionary

我的目標是將從call web api取回的巢狀JSON轉成結構化的字串,顯示在畫面上。

網路上能輕易找到JSON反序列化(Deserialize)成Data Model Class Object的做法。反序列方法很強大,當Data Model Class是巢狀時,它能自動將巢狀JSON字串反列化成巢狀的Data Model Class Object。

不過,當我要將巢狀JSON字串轉成Key(欄位) : Value(值)這樣的字串,一行顯示一對,且要具有巢狀結構,這就需要自己寫了。

最後我完成的做法請看:【C#】【JSON】將JSON字串(巢狀、{開頭的、[開頭的...)解析(parse)為結構化的字串

本篇收錄的是我在思考JSON轉巢狀Dictionary時,找到的一些資料,留作參考。

摘自:Json.NET: Deserializing nested dictionaries
https://stackoverflow.com/questions/6416017/json-net-deserializing-nested-dictionaries

●這方法省code:

I had a very similar but slightly more complex need when I ran across this Q. At first I thought maybe I could adapt the accepted answer, but that seemed a bit complicated and I ended up taking a different approach. I was attempting to put a modern JSON layer on top of a legacy C++ API. I'll spare you the details of that, and just say the requirements boil down to:

JSON objects become Dictionary<string,object>.

JSON arrays become List<object>.

JSON values become the corresponding primitive CLR values.

The objects and arrays can be infinitely nested.

I first deserialize the request string into a Newtonsoft JSON object and then call my method to convert in accordance with the above requirements:

var jsonObject = JsonConvert.DeserializeObject(requestString);
var apiRequest = ToApiRequest(jsonObject);
// call the legacy C++ API ...

Here is my method that converts to the structure the API expects:

    private static object ToApiRequest(object requestObject)
    {
        switch (requestObject)
        {
            case JObject jObject: // objects become Dictionary<string,object>
                return ((IEnumerable<KeyValuePair<string, JToken>>) jObject).ToDictionary(j => j.Key, j => ToApiRequest(j.Value));
            case JArray jArray: // arrays become List<object>
                return jArray.Select(ToApiRequest).ToList();
            case JValue jValue: // values just become the value
                return jValue.Value;
            default: // don't know what to do here
                throw new Exception($"Unsupported type: {requestObject.GetType()}");
        }
    }

feedback:

This was really useful. I was unable to decode this kind of response with the given solution. {"id":2,"name":"root","descendants":[{"id":4,"name":"node2","descendants":[{"id":7,"name":"node21"},{"id":8,"name":"node22"}]},{"id":3,"name":"node1","descendants":[{"id":5,"name":"node11"},{"id":6,"name":"node12"}]}]}. Thanks – Pushpa Kumara May 28, 2021 at 11:56 


●另一方法,供參考:


        #region Nested Dictionary
        //You will want to add null checks, and other exit cases otherwise you will quickly end up in an infinate loop.This is just to get you started.

        public Dictionary<string, string> MapToDictionary(object source, string name)
        {
            var dictionary = new Dictionary<string, string>();
            MapToDictionaryInternal(dictionary, source, name);
            return dictionary;
        }

        private void MapToDictionaryInternal(Dictionary<string, string> dictionary, object source, string name)
        {
            var properties = source.GetType().GetProperties();
            foreach (var p in properties)
            {
                var key = name + "." + p.Name;
                object value = p.GetValue(source, null);
                Type valueType = value.GetType();

                if (valueType.IsPrimitive || valueType == typeof(String))
                {
                    dictionary[key] = value.ToString();
                }
                else if (value is IEnumerable)
                {
                    var i = 0;
                    foreach (object o in (IEnumerable)value)
                    {
                        MapToDictionaryInternal(dictionary, o, key + "[" + i + "]");
                        i++;
                    }
                }
                else
                {
                    MapToDictionaryInternal(dictionary, value, key);
                }
            }
        }

        //Call it like this:
        //Dictionary<string, string> dictionary2 = MapToDictionary(agreement, "Agreement");
        #endregion

 


JToken和JObject有什么区别

https://blog.csdn.net/chelen_jak/article/details/106376237?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&utm_relevant_index=1 

一、JToken和JObject有什么区别
原文出处:JToken和JObject有什么区别 - 八英里 - 博客园
JObject  用于操作JSON对象
JArray    用语操作JSON数组
JValue   表示数组中的值
JProperty 表示对象中的属性,以"key/value"形式
JToken  用于存放Linq to JSON查询后的结果

二、(译)JToken的层次结构
 

原文地址:https://stackoverflow.com/questions/38558844/jcontainer-jobject-jtoken-and-linq-confusion/38560188#38560188?newreg=577582085c60496db7bdb78be26a2313

 

JToken的层次结构是这样的:


JToken          -抽象基类
  JContainer     - 能够包含其它JToken的JToken抽象基类
    JArray     - 表示一个JSON数组(包含一个有序的List<JToken>)
    JObeject      - 表示一个JSON对象(包含一个IEnumerable<JProperty>)
    JProperty     - 表示一个JSON属性(在JObject中是一个name/JToken键值对)
  JValue       - 表示一个原生JSON值(string,number,boolean,null)


以下是几条基本的经验法则:

  • 如果是一个对象(在JSON里是有大括号“{”和“}”来标识的),就用JObject。
  • 如果是一个数组或集合(用中括号“[”和“]”标识的),就用JArray。
  • 如果是原生值,就用JValue。
  • 如果你不知道你的json是什么类型的token,或者你希望用一种通用的方式来处理上面任意一种类型的对象,就用JToken,然后你可以检查它的Type属性来决定是哪种类型的token,并把它转化成相应的类型。

三、 C# JTOKEN类的使用,实现解析动态JSON数据、遍历、查找
https://www.freesion.com/article/2598272928/


[C#][筆記] IEnumerable、IEnumerator 與 IEnumerable、IEnumerator

http://vegeee-csharp.blogspot.com/2017/02/c-ienumerableienumerator-ienumerable.html