【C#】复杂Json的反序列 + 任意Json获取

前言

本文用到的Json库是:

 以前用这个

 但是,现在微软主推上面这个,性能更优,用法其实差不多。

复杂结构的JSON

如何将一个复杂类型的JSON进行反序列化。那就是如何把json拆解成一个个子类的过程。

如下我有这样一个json字符串:

{
            "success": True,
            "message": "操作成功!",
            "code": 200,
            "result": {
                "ruleColumn": [
                    {
                        "columnChName": "孔宽1"
                    },
                    {
                        "columnChName": "孔从中心偏移3"
                    },
                    {
                        "columnChName": "孔从中心偏移6"
                    },
                    {
                        "columnChName": "孔从中心偏移5"
                    },
                    {
                        "columnChName": "孔从中心偏移2"
                    },
                    {
                        "columnChName": "孔长3"
                    },
                    {
                        "columnChName": "孔从中心偏移7"
                    },
                    {
                        "columnChName": "孔从中心偏移4"
                    },
                    {
                        "columnChName": "孔中到Y中心8"
                    },
                    {
                        "columnChName": "孔中到X中心9"
                    }
                ],
                "number": 5,
                "titleColumn": [
                    {
                        "columnChName": "工序",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "日期",
                        "columnType": "date",
                        "selectValue": None
                    },
                    {
                        "columnChName": "班次",
                        "columnType": "select",
                        "selectValue": [
                            "A",
                            "B"
                        ]
                    },
                    {
                        "columnChName": "测试时间",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "测试员",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "测试机台号",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "备注",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "生产机台",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "检验方式",
                        "columnType": "input",
                        "selectValue": None
                    },
                    {
                        "columnChName": "判定",
                        "columnType": "judge",
                        "selectValue": None
                    }
                ],
                "projectDetailId": "1559817674652483586",
                "rules": [
                    {
                        "columnChName": "孔宽1",
                        "nominalDim": 17.28,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 17.3,
                        "lsl": 17.26
                    },
                    {
                        "columnChName": "孔从中心偏移3",
                        "nominalDim": 17.28,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 17.3,
                        "lsl": 17.26
                    },
                    {
                        "columnChName": "孔从中心偏移6",
                        "nominalDim": 17.28,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 17.3,
                        "lsl": 17.26
                    },
                    {
                        "columnChName": "孔从中心偏移5",
                        "nominalDim": 13.84,
                        "tolMax": 0.05,
                        "tolMin": 0.05,
                        "usl": 13.89,
                        "lsl": 13.79
                    },
                    {
                        "columnChName": "孔从中心偏移2",
                        "nominalDim": 13.84,
                        "tolMax": 0.05,
                        "tolMin": 0.05,
                        "usl": 13.89,
                        "lsl": 13.79
                    },
                    {
                        "columnChName": "孔长3",
                        "nominalDim": 52.94,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 52.96,
                        "lsl": 52.92
                    },
                    {
                        "columnChName": "孔从中心偏移7",
                        "nominalDim": 49.75,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 49.77,
                        "lsl": 49.73
                    },
                    {
                        "columnChName": "孔从中心偏移4",
                        "nominalDim": 49.75,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 49.77,
                        "lsl": 49.73
                    },
                    {
                        "columnChName": "孔中到Y中心8",
                        "nominalDim": 43.99,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 44.01,
                        "lsl": 43.97
                    },
                    {
                        "columnChName": "孔中到X中心9",
                        "nominalDim": 16.23,
                        "tolMax": 0.02,
                        "tolMin": 0.02,
                        "usl": 16.25,
                        "lsl": 16.21
                    }
                ]
            },
            "timestamp": 1663056576303
        }

其中result这个key对应的内容是可能发生变化的,所以这里可以用到泛型。大体不变的框架是这样的:

{
            "success": True,
            "message": "添加成功!",
            "code": 200,
            "result": None,
            "timestamp": int(round(time.time() * 1000))
}

类的构造

那我先构造这个类,对于大的框架:

注意,类名并不重要(他代表的是大括号)重要的是属性的名称,需要和key的值保持一致:

public class WeiDaLiResult<T>
{
    public bool success { get; set; }
    public string message { get; set; }
    public int code { get; set; }
    public T result { get; set; }
    public ulong timestamp { get; set; }
}

然后是针对当前result的部分,这里的技术关键是如何构造json数组,我们用到了IList接口:

    #region item 项
    public class RuleColumnItem
    {
        public string columnChName { get; set; }
    }

    public class TitleColumnItem
    {
        public string columnChName { get; set; }
        public string columnType { get; set; }
        public IList<string> selectValue { get; set; }
    }
    public class RulesItem
    {
        public string columnChName { get; set; }
        public float nominalDim { get; set; }
        public float tolMax { get; set; }
        public float tolMin { get; set; }
        public float usl { get; set; }
        public float lsl { get; set; }
    }
    #endregion

    public class SubResult
    {
        public IList<RuleColumnItem> ruleColumn { get; set; }
        public int number { get; set; }
        public IList<TitleColumnItem> titleColumn { get; set; }
        public string projectDetailId { get; set; }
        public IList<RulesItem> rules { get; set; }

    }

反序列化过程调用

反序列化过程调用(注意泛型是如何被使用的):

var r = System.Text.Json.JsonSerializer.Deserialize<WeiDaLiResult<SubResult>>(str_json);

中文乱码解决

这里我们可以把这个options 保存到wpf的App类中,方便其他类调用。

public static JsonSerializerOptions options = new JsonSerializerOptions()
        {
            // 解决中文乱码问题
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All)
        };

比如一个类想序列化成json字符串:

我们就可以用:

var byteArray = JsonSerializer.SerializeToUtf8Bytes(this, App.options);

完整代码如下: 

public class ReturnInfo<T>
{
    

    public bool success { get; set; }
    public string message { get; set; }
    public string code { get; set; }
    public T result { get; set; }
    public long timestamp 
    { 
        get 
        {
          return  DateTimeOffset.Now.ToUnixTimeSeconds();
        } 
    }


    public override string ToString()
    {
        var byteArray = JsonSerializer.SerializeToUtf8Bytes(this, App.options);
        string str = System.Text.Encoding.UTF8.GetString(byteArray);
        return str;
    }
}

或者obj本身就是一个json,则使用:

obj.ToJsonString(options)

套路就是,json对象转换成字符串或者字节数组的时候,都会有重载函数,其中就有一个带options参数的,把这个options传入,就能解决乱码问题啦!

枚举的反序列化

这里在做一个优化:

将columnType这个字段序列化成枚举。

[JsonConverter(typeof(JsonStringEnumConverter))]

public enum ControlType
{
    input = 0,
    date,
    select,
    judge,
}

类改造

//改造前
public class TitleColumnItem
{
    public string columnChName { get; set; }
    public string columnType { get; set; }
    public IList<string> selectValue { get; set; }
}


//改造后
public class TitleColumnItem
{
    public string columnChName { get; set; }
    public ControlType columnType { get; set; }
    public IList<string> selectValue { get; set; }
}

注意,枚举要序列化,需要加一个特性:

[JsonConverter(typeof(JsonStringEnumConverter))]

任意Json获取

在有的情况下,我们只得到一个json字符串,并没有一个模板来进行序列化,也就是说,这个json的Key是不确定的,那么我们应该这么访问这个json字符串呢?

我们需要一个叫JsonDocument的类帮忙:

var je = System.Text.Json.JsonDocument.Parse(jsonStr);

比如我们的字符串是:

{"1长 X0":0.01, "12 长 X-26.89":0.07, "判定":"OK"}

我们就可以这么获取值:

var s = je.RootElement.GetProperty("1长 X0").GetDouble();

Json 格式化

想分行显示json,然后带缩进,本来Newtonsoft.Json是自带这个功能的:

string json = JsonConvert.SerializeObject(product, Formatting.Indented);

微软自带的这个包,我还没发现有这个功能,所以,这里就提供一个类来实现吧:

public class JsonHelper
    {
        private const string INDENT_STRING = "    ";
        public static string FormatJson(string str)
        {
            var indent = 0;
            var quoted = false;
            var sb = new StringBuilder();
            for (var i = 0; i < str.Length; i++)
            {
                var ch = str[i];
                switch (ch)
                {
                    case '{':
                    case '[':
                        sb.Append(ch);
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, ++indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        break;
                    case '}':
                    case ']':
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, --indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        sb.Append(ch);
                        break;
                    case '"':
                        sb.Append(ch);
                        bool escaped = false;
                        var index = i;
                        while (index > 0 && str[--index] == '\\')
                            escaped = !escaped;
                        if (!escaped)
                            quoted = !quoted;
                        break;
                    case ',':
                        sb.Append(ch);
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        break;
                    case ':':
                        sb.Append(ch);
                        if (!quoted)
                            sb.Append(" ");
                        break;
                    default:
                        sb.Append(ch);
                        break;
                }
            }
            return sb.ToString();
        }


    }

    static class Extensions
    {
        public static void MyForEach<T>(this IEnumerable<T> ie, Action<T> action)
        {
            foreach (var i in ie)
            {
                action(i);
            }
        }
    }

posted @ 2022-09-13 22:08  宋桓公  阅读(180)  评论(0编辑  收藏  举报