小编典典

通常使用C#展平Json

json

我想一般地展平一些json,以便我可以使用c#转换为数据表并绑定到datagrid

考虑到我不知道我要下降多少级别,最好的控制方式是什么?

例如

{
  “ appointmentid”:4
  “ policyid”:1,
  “ guid”:“ 00000000-0000-0000-0000-000000000000”,
  “ number”:“ 1234567890”,
  “ ampm”:“ false”,
  “ date”:“ 2015-09-08T00:00:00”,
  “车辆”:{
    “ id”:1
    “ guid”:“ 00000000-0000-0000-0000-000000000000”,
    “ make”:null,
    “型号”:null
  },
  “安装程序”:{
    “ installerid”:“ 1”,
    “ name”:“安装程序1”,
    “联系人”:“ qwerty”,
    “ qascore”:“ 0”,
    “ address1”:“ qwerty”,
    “ address2”:“ qwerty”,
    “ address3”:null,
    “ address4”:null,
    “ city”:“ qwertyu”,
    “ county”:“ qwertyu”,
    “邮政编码”:“ asdfghj”,
    “ country”:“ GB”,
    “ email”:“ asdfghj”,
    “ web”:“ asdfghjk”,
    “已存档”:false
  },
  “安装”:[
    {
      “ installationid”:6
      “ installationstatus”:{
        “ installationstatusid”:4
        “ installationstatus”:“失败”
      },
      “无效”:true
    },
    {
      “ installationid”:7
      “ installationstatus”:{
        “ installationstatusid”:1
        “ installationstatus”:“ NEW”
      },
      “无效”:false
    }
  ],
  “已存档”:false
}

我想扩展它(我想我可以对转换后的数据表进行迭代),而不是installations.1.installationid,我将得到installationid1。

因为我要在网格中显示结果数据表,所以我想保持列名友好。


阅读 370

收藏
2020-07-27

共1个答案

小编典典

您可以使用Json.Net的LINQ-to-JSON
API
将数据解析为JToken结构。从那里,您可以使用递归帮助器方法来遍历结构并将其展平到Dictionary<string, object>键是原始JSON中每个值的“路径”的位置。我会这样写:

public class JsonHelper
{
    public static Dictionary<string, object> DeserializeAndFlatten(string json)
    {
        Dictionary<string, object> dict = new Dictionary<string, object>();
        JToken token = JToken.Parse(json);
        FillDictionaryFromJToken(dict, token, "");
        return dict;
    }

    private static void FillDictionaryFromJToken(Dictionary<string, object> dict, JToken token, string prefix)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                foreach (JProperty prop in token.Children<JProperty>())
                {
                    FillDictionaryFromJToken(dict, prop.Value, Join(prefix, prop.Name));
                }
                break;

            case JTokenType.Array:
                int index = 0;
                foreach (JToken value in token.Children())
                {
                    FillDictionaryFromJToken(dict, value, Join(prefix, index.ToString()));
                    index++;
                }
                break;

            default:
                dict.Add(prefix, ((JValue)token).Value);
                break;
        }
    }

    private static string Join(string prefix, string name)
    {
        return (string.IsNullOrEmpty(prefix) ? name : prefix + "." + name);
    }
}

将此DeserializeAndFlatten方法与JSON结合使用,最终会得到像这样的键值对:

appointmentid: 4
policyid: 1
guid: 00000000-0000-0000-0000-000000000000
number: 1234567890
ampm: false
date: 9/8/2015 12:00:00 AM
vehicle.id: 1
vehicle.guid: 00000000-0000-0000-0000-000000000000
vehicle.make:
vehicle.model:
installer.installerid: 1
installer.name: Installer 1
installer.contact: qwerty
installer.qascore: 0
installer.address1: qwerty
installer.address2: qwerty
installer.address3:
installer.address4:
installer.city: qwertyu
installer.county: qwertyu
installer.postcode: asdfghj
installer.country: GB
installer.email: asdfghj
installer.web: asdfghjk
installer.archived: False
installations.0.installationid: 6
installations.0.installationstatus.installationstatusid: 4
installations.0.installationstatus.installationstatus: FAIL
installations.0.isactive: True
installations.1.installationid: 7
installations.1.installationstatus.installationstatusid: 1
installations.1.installationstatus.installationstatus: NEW
installations.1.isactive: False
archived: False

如果您希望使这些按键更人性化,则可以使用一些字符串操作来将其缩减。也许是这样的:

var dict = JsonHelper.DeserializeAndFlatten(json);
foreach (var kvp in dict)
{
    int i = kvp.Key.LastIndexOf(".");
    string key = (i > -1 ? kvp.Key.Substring(i + 1) : kvp.Key);
    Match m = Regex.Match(kvp.Key, @"\.([0-9]+)\.");
    if (m.Success) key += m.Groups[1].Value;
    Console.WriteLine(key + ": " + kvp.Value);
}

那会给你这个输出:

appointmentid: 4
policyid: 1
guid: 00000000-0000-0000-0000-000000000000
number: 1234567890
ampm: false
date: 9/8/2015 12:00:00 AM
id: 1
guid: 00000000-0000-0000-0000-000000000000
make:
model:
installerid: 1
name: Installer 1
contact: qwerty
qascore: 0
address1: qwerty
address2: qwerty
address3:
address4:
city: qwertyu
county: qwertyu
postcode: asdfghj
country: GB
email: asdfghj
web: asdfghjk
archived: False
installationid0: 6
installationstatusid0: 4
installationstatus0: FAIL
isactive0: True
installationid1: 7
installationstatusid1: 1
installationstatus1: NEW
isactive1: False
archived: False

但是请注意,通过这种安排,您已经失去了一些上下文:例如,您可以看到现在有两个相同的archived键,而在原始JSON中,它们是不同的,因为它们出现在层次结构的不同部分(installer.archivedvs.
archived)。您将需要弄清楚如何自行处理该问题。

小提琴:https :
//dotnetfiddle.net/gzhWHk

2020-07-27