当前位置: 首页 > 面试题库 >

通常使用C#展平Json

融修平
2023-03-14
问题内容

我想一般地展平一些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。

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


问题答案:

您可以使用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



 类似资料:
  • 本文向大家介绍如何使用LINQ C#展平列表?,包括了如何使用LINQ C#展平列表?的使用技巧和注意事项,需要的朋友参考一下 展平列表意味着将List <List <T >>转换为List <T>。例如,让我们考虑一个List <List <int >>,它需要转换为List <int>。 LINQ中的SelectMany用于将序列的每个元素投影到IEnumerable <T>,然后将所得序列展

  • 问题内容: 我在C#中有一个json对象(表示为Newtonsoft.Json.Linq.JObject对象),我需要将其展平为字典。让我向您展示我的意思的示例: 这将产生一个包含以下键值对的字典: 我怎样才能做到这一点? 问题答案: 我有将嵌套的json结构展平为字典对象的相同要求。在这里找到解决方案。

  • 问题内容: 我想拉平一个嵌套的JSON对象,如以为了消化它Solr中。 我有11 TB的json文件,这些文件既嵌套又包含字段名称中的点,这意味着elasticsearch(点)或solr(嵌套时不带符号)都不能按原样消化它。 其他解决方案是用下划线替换字段名称中的点并将其推送到elasticsearch,但是我对solr有更好的经验,因此我更喜欢扁平化解决方案(除非solr可以按原样消化那些嵌套

  • Im使用net.sf.json.JSONArray和net . SF . JSON . JSONObject . JSON array包含多个JSON object。 基本上是这样的: 我想用Java 8来解决这个问题,即结果:

  • 本文向大家介绍Ruby使用C++扩展实例(含C++扩展代码示例),包括了Ruby使用C++扩展实例(含C++扩展代码示例)的使用技巧和注意事项,需要的朋友参考一下 早年写过用C++ + SWIG写Ruby插件的文,但实际中还是以原生C++写Ruby扩展,因为也相当简单。但长久没用还是会忘记,不得不翻以前的老代码回忆,写下这篇博文,若下次再忘记,也不至于去翻仓库。 建立 extconf.rb 建立

  • 问题内容: 说我有一个 我可以很容易地获得地图的值,并对其进行迭代以生成一个。 有一种方法可以一次压平吗? 问题答案: 如果您使用的是Java 8,则可以执行以下操作: