【问题标题】:Converting an abnormal JSON string to List<class>将异常 JSON 字符串转换为 List<class>
【发布时间】:2019-08-31 06:17:23
【问题描述】:

我遇到了来自另一家公司的 Web 服务,它返回异常的 JSON 字符串。

这是 JSON 的样子:

["TERMINAL_NO","METER_NO","RAMZE_RAYANEH_SHENASE_GHABZ","PARVANDEH_ESHTERAK","POWER_UTILITY","CT_RATIO","PT_RATIO","NAME_","PART","CUSTOMER_ID","X_POS","Y_POS","DATE_NUM","HOUR_NUM","MONTH_","DAY_","YEAR_","DAY_WEEK","MONTH_DAY","DATE_HOUR","ACTIVE_ENERGY_PLUS_TOTAL","ACTIVE_ENERGY_PLUS_TARIF_1","ACTIVE_ENERGY_PLUS_TARIF_2","ACTIVE_ENERGY_PLUS_TARIF_3","ACTIVE_ENERGY_PLUS_TARIF_4","ACTIVE_ENERGY_MINUS_TOTAL","ACTIVE_ENERGY_MINUS_TARIF_1","ACTIVE_ENERGY_MINUS_TARIF_2","ACTIVE_ENERGY_MINUS_TARIF_3","ACTIVE_ENERGY_MINUS_TARIF_4","REACTIVE_ENERGY_PLUS_TOTAL","REACTIVE_ENERGY_PLUS_TARIF_1","REACTIVE_ENERGY_PLUS_TARIF_2","REACTIVE_ENERGY_PLUS_TARIF_3","REACTIVE_ENERGY_PLUS_TARIF_4","REACTIVE_ENERGY_MINUS_TOTAL","REACTIVE_ENERGY_MINUS_TARIF_1","REACTIVE_ENERGY_MINUS_TARIF_2","REACTIVE_ENERGY_MINUS_TARIF_3","REACTIVE_ENERGY_MINUS_TARIF_4","VOLTAGE_PHASE_A","VOLTAGE_PHASE_B","VOLTAGE_PHASE_C","CURRENT_PHASE_A","CURRENT_PHASE_B","CURRENT_PHASE_C","POWER_ACTIV_AVG","POWER_ACTIV_MIN","POWER_ACTIV_MAX","POWER_REACT_AVG","POWER_REACT_MIN","POWER_REACT_MAX","POWER_FACTOR_PHASE_A","POWER_FACTOR_PHASE_B","POWER_FACTOR_PHASE_C","READ_FLAG"],
["039530059094","039530059094","8448430104225","2420815","\u06a9\u0646\u062a\u0648\u0631\u0647\u0627\u06cc \u062f\u06cc\u0645\u0627\u0646\u062f\u06cc \u0627\u0633\u062a\u0627\u0646 \u062a\u0647\u0631\u0627\u0646","100\/5","1\/1","Ali Falahi","\u06af\u0644\u0633\u062a\u0627\u0646","2420815",null,null,"13980607","0","06","07","1398","\u067e\u0646\u062c \u0634\u0646\u0628\u0647","0607","0607.0",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"OFFLINE"],
["039530059094","039530059094","8448430104225","2420815","\u06a9\u0646\u062a\u0648\u0631\u0647\u0627\u06cc \u062f\u06cc\u0645\u0627\u0646\u062f\u06cc \u0627\u0633\u062a\u0627\u0646 \u062a\u0647\u0631\u0627\u0646","100\/5","1\/1","Ali Falahi","\u06af\u0644\u0633\u062a\u0627\u0646","2420815",null,null,"13980607","1","06","07","1398","\u067e\u0646\u062c \u0634\u0646\u0628\u0647","0607","0607.1",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"OFFLINE"]

第一行数据是列名,其余是数据。 既然我不能告诉他们改变他们的数据格式,我怎么能把它转换成类列表或任何类似具有相关列的键值对列表?

【问题讨论】:

  • 你还不如使用 csv,这个 JSON 不是很有用,你将无法将它解析成有用的类(除了对象列表)。
  • 这肯定不是有效的 JSON。正如@Hytam 建议的那样,我会使用 CsvHelper 等辅助类将其视为 CSV,但您首先需要读取字符串并删除额外的 [ ] 字符

标签: c# json list


【解决方案1】:

这取决于您计划如何使用这些数据。我的猜测是,您需要能够将第一行的元素与第 1 到第 n 行中的数据配对。所以也许期望的输出是一个字典列表。

如果是这种情况,我建议您将其解析为 JSON(而不是 CSV——转义规则不同),然后将字段映射到您需要的数据结构中。例如:

var array = JsonConvert.DeserializeAnonymousType("[" + input + "]" , (string[][])null);
Console.WriteLine("There were {0} rows with {1} columns", array.Length, array[0].Length);
var list = new List<Dictionary<string,string>>();
for (var i = 1; i<= array.GetUpperBound(0); i++)
{
    var dictionary = array[0]
        .Zip(array[i], (l,r) => new KeyValuePair<string,string>(l,r))
        .ToDictionary( pair => pair.Key, pair => pair.Value);
    list.Add(dictionary);
}

Console.WriteLine("We now have a list of {0} rows", list.Count);

for (int i=0; i<list.Count; i++)
{
    Console.WriteLine("\r\nHere is row {0}\r\n", i);
    var dictionary = list[i];
    foreach (var key in dictionary.Keys)
    {
        Console.WriteLine("{0} = {1}", key, dictionary[key]);
    }
}

输出如下所示:

There were 3 rows with 56 columns
We now have a list of 2 rows

Here is row 0

TERMINAL_NO = 039530059094
METER_NO = 039530059094
RAMZE_RAYANEH_SHENASE_GHABZ = 8448430104225
PARVANDEH_ESHTERAK = 2420815
POWER_UTILITY = ???????? ??????? ????? ?????
CT_RATIO = 100/5
PT_RATIO = 1/1
NAME_ = Ali Falahi
PART = ??????
CUSTOMER_ID = 2420815
X_POS = 
Y_POS = 
DATE_NUM = 13980607
HOUR_NUM = 0
MONTH_ = 06
DAY_ = 07
YEAR_ = 1398
DAY_WEEK = ??? ????
MONTH_DAY = 0607
DATE_HOUR = 0607.0
ACTIVE_ENERGY_PLUS_TOTAL = 
ACTIVE_ENERGY_PLUS_TARIF_1 = 
ACTIVE_ENERGY_PLUS_TARIF_2 = 
ACTIVE_ENERGY_PLUS_TARIF_3 = 
ACTIVE_ENERGY_PLUS_TARIF_4 = 
ACTIVE_ENERGY_MINUS_TOTAL = 

这是一个工作Fiddle的链接

【讨论】:

    【解决方案2】:

    如果您想从另一端获得一个不错的类列表,则需要做一些工作来将几乎 CSV 样式的 JSON 转换为可以反序列化为类型对象列表的内容,例如:

    using System.Collections.Generic;
    using System.Linq;
    using Newtonsoft.Json; // Install-Module Newtonsoft.JSON
    
    namespace StackOverflow
    {
        public class PowerReading
        {
            [JsonProperty("TERMINAL_NO")]
            public string TerminalNumber { get; set; }
            [JsonProperty("METER_NO")]
            public string MeterNumber { get; set; }
            public string RAMZE_RAYANEH_SHENASE_GHABZ { get; set; }
            public string PARVANDEH_ESHTERAK { get; set; }
            [JsonProperty("POWER_UTILITY")]
            public string PowerUtility { get; set; }
            public string CT_RATIO { get; set; }
            public string PT_RATIO { get; set; }
            [JsonProperty("NAME_")]
            public string Name { get; set; }
            public string Part { get; set; }
            [JsonProperty("CUSTOMER_ID")]
            public string CustomerId { get; set; }
            [JsonProperty("X_POS")]
            public string XPos { get; set; }
            [JsonProperty("Y_POS")]
            public string YPos { get; set; }
            public string DATE_NUM { get; set; }
            public string HOUR_NUM { get; set; }
            public string MONTH_ { get; set; }
            public string DAY_ { get; set; }
            public string YEAR_ { get; set; }
            public string DAY_WEEK { get; set; }
            public string DATE_HOUR { get; set; }
            public string ACTIVE_ENERGY_PLUS_TOTAL { get; set; }
            public string ACTIVE_ENERGY_PLUS_TARRIF1 { get; set; }
            public string ACTIVE_ENERGY_PLUS_TARRIF2 { get; set; }
            public string ACTIVE_ENERGY_PLUS_TARRIF3 { get; set; }
            public string ACTIVE_ENERGY_PLUS_TARRIF4 { get; set; }
            public string ACTIVE_ENERGY_MINUS_TOTAL { get; set; }
            public string ACTIVE_ENERGY_MINUS_TARRIF1 { get; set; }
            public string ACTIVE_ENERGY_MINUS_TARRIF2 { get; set; }
            public string ACTIVE_ENERGY_MINUS_TARRIF3 { get; set; }
            public string ACTIVE_ENERGY_MINUS_TARRIF4 { get; set; }
            public string REACTIVE_ENERGY_PLUS_TOTAL { get; set; }
            public string REACTIVE_ENERGY_PLUS_TARRIF1 { get; set; }
            public string REACTIVE_ENERGY_PLUS_TARRIF2 { get; set; }
            public string REACTIVE_ENERGY_PLUS_TARRIF3 { get; set; }
            public string REACTIVE_ENERGY_PLUS_TARRIF4 { get; set; }
            public string REACTIVE_ENERGY_MINUS_TOTAL { get; set; }
            public string REACTIVE_ENERGY_MINUS_TARRIF1 { get; set; }
            public string REACTIVE_ENERGY_MINUS_TARRIF2 { get; set; }
            public string REACTIVE_ENERGY_MINUS_TARRIF3 { get; set; }
            public string REACTIVE_ENERGY_MINUS_TARRIF4 { get; set; }
            public string VOLTAGE_PHASE_A { get; set; }
            public string VOLTAGE_PHASE_B { get; set; }
            public string VOLTAGE_PHASE_C { get; set; }
            public string CURRENT_PHASE_A { get; set; }
            public string CURRENT_PHASE_B { get; set; }
            public string CURRENT_PHASE_C { get; set; }
            public string POWER_ACTIV_AVG { get; set; }
            public string POWER_ACTIV_MIN { get; set; }
            public string POWER_ACTIV_MAX { get; set; }
            public string POWER_REACT_AVG { get; set; }
            public string POWER_REACT_MIN { get; set; }
            public string POWER_REACT_MAX { get; set; }
            public string POWER_FACTOR_PHASE_A { get; set; }
            public string POWER_FACTOR_PHASE_B { get; set; }
            public string POWER_FACTOR_PHASE_C { get; set; }
            public string READ_FLAG { get; set; }
        }
    
        class MainClass
        {
            public static void Main(string[] args)
            {
                //First JSON pass: fix the JSON up enough to read in as an array of string arrays.
                var badJson = System.IO.File.ReadAllText("web_service.json");
                var arrayOfStringArrays = JsonConvert.DeserializeObject<string[][]>("[" + badJson + "]");
    
                //Use the first row as column headings (aka Object Property Names).
                var headings = arrayOfStringArrays.Take(1).FirstOrDefault();
    
                //Convert the remaining rows to a List of Dictionary<string,string> objects.
                var data = arrayOfStringArrays
                    .Skip(1)
                    .Select(row =>
                    {
                        var colIndex = 0;
                        var dictionary = new System.Collections.Generic.Dictionary<string, string>();
                        row.ToList().ForEach(col => dictionary.Add(headings[colIndex++], col));
                        return dictionary;
                    });
    
                //Serialize the List<Dictionary<string,string>> back to JSON.
                var goodJson = JsonConvert.SerializeObject(data);
    
                //Now we can deserialize the JSON to list of typed objects.
                var powerReadings = JsonConvert.DeserializeObject<IList<PowerReading>>(goodJson);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      JSON 就像一个二维数组,只是它缺少外部数组的开始和结束。您可以恢复它们,然后解析为二维字符串数组:

      var result = JsonConvert.DeserializeObject<string[][]>(jsonMessage);
      

      【讨论】:

        猜你喜欢
        • 2019-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-05
        相关资源
        最近更新 更多