【问题标题】:Read JSON file into a Jarray and access data dynamically将 JSON 文件读入 Jarray 并动态访问数据
【发布时间】:2016-11-09 14:44:28
【问题描述】:

我正在尝试将一个非常复杂的 json 文件读入一个可以在 foreach 语句中动态访问的 JArray。但是,我收到一条错误消息,指出“当前 JsonReader 项目不是数组”如果我使用 JObject,我可以访问键和值,但这不是我需要能够浏览记录和按名称或 ID 等搜索。我对 newtwonsoft 和 JSON.net 有点陌生,因此我们将不胜感激!

JArray o1 = JArray.Parse(File.ReadAllText(@"myfilepath"));

dynamic records = o1;

foreach (dynamic record in records)
{
       Console.WriteLine(record.Id + " (" + record.Name + ")");
}

我的 json 文件看起来像这样,有多个记录但是我已经缩短了它。我需要按 ID 或名称进行访问和搜索,但是我在访问时遇到问题。

String json = @"{
  "RecordSetBundles" : [ {
    "Records" : [ {
      "attributes" : {
        "type" : "nihrm__Location__c",
        "url" : "/services/data/v38.0/sobjects/nihrm__Location__c/a0di0000001nI3oAAE"
      },
      "CurrencyIsoCode" : "USD",
      "Id" : "a0di0000001nI3oAAE",
      "Name" : "The City Hotel",
      "nihrm__Abbreviation__c" : "TCH",
      "nihrm__AddressLine1__c" : "1 Main Street",
      "nihrm__AlternateNameES__c" : "El Ciudad Hotel",
      "nihrm__AvailabilityScreenView__c" : "Combined",
      "nihrm__Geolocation__c" : null,
      "nihrm__HideBookingsFromPortal__c" : false,
      "nihrm__IsActive__c" : true,
      "nihrm__IsPlannerPortalEnabled__c" : false,
      "nihrm__isRemoveCancelledEventsFromBEOs__c" : false,
      "nihrm__ManagementAffliation__c" : "NI International",
      "nihrm__NearestAirportCode__c" : "MHT",
      "nihrm__Phone__c" : "(207) 555-5555",
      "nihrm__PostalCode__c" : "04103",
      "nihrm__PropertyCode__c" : "TCH",
      "nihrm__RegionName__c" : "Northeast",
      "nihrm__RestrictBookingMoveWithPickup__c" : true,
      "nihrm__RohAllowedStatuses__c" : "Prospect;Tentative;Definite",
      "nihrm__StateProvince__c" : "ME",
      "nihrm__SystemOfMeasurement__c" : "Standard",
      "nihrm__TimeZone__c" : "GMT-05:00 Eastern Daylight Time (America/New_York)",
      "nihrm__UpdateBookingEventAverageChecks__c" : false,
      "nihrm__UseAlternateLanguage__c" : false,
      "nihrm__Website__c" : "www.thecityhotelweb.com"
    } ],
    "ObjectType" : "nihrm__Location__c",
    "DeleteFirst" : false
  },

这里是整个 json 的链接: https://codeshare.io/rGL6K5

【问题讨论】:

  • 您应该显示您尝试解析的 json。错误可能是因为 json 是 JsonObject,而不是 JsonArray。
  • 您可以尝试直接反序列化为dynamic 对象:var records = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(@"myfilepath"));。您需要显示相关的 JSON 以获得进一步的帮助。
  • @Equalsk 谢谢你,我要试一试,看看哪个最适合我。如果它运作良好,我会通知您,以便您提交答案!
  • @Equalsk 我已经尝试过了,但仍然无法访问 json 数据,请原谅我对此很陌生。我已经添加了我的 json 文件的部分内容
  • 你能添加整个 JSON 字符串吗?或者,如果它真的很长,像所有不同的nihrm_ 位一样删除了很多不必要的细节。很难仅对图片的一部分提供帮助。

标签: c# arrays json.net


【解决方案1】:

其他答案显示强类型类。如果你能做到这一点并且你确定结构不会改变,我建议你这样做。它会让一切变得更容易。

如果你想用动态对象来做,那么你可以通过这种方式得到你想要的。

// GET JSON DATA INTO DYNAMIC OBJECT
var data  = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(@"myfilepath"));

// GET TOP LEVEL "RecordSetBundles" OBJECT
var bundles = data.RecordSetBundles;

// LOOP THROUGH EACH BUNDLE OF RECORDS
foreach (var bundle in bundles)
{
    // GET THE RECORDS IN THIS BUNDLE
    var records = bundle.Records;

    // LOOP THROUGH THE RECORDS
    foreach (var record in records)
    {
        // WRITE TO CONSOLE
        Console.WriteLine(record.Id.ToString() + " (" + record.Name.ToString() + ")");
    }
}

产生这个输出:

a0di0000001nI3oAAE(城市酒店)
a0xi0000000jOQCAA2(8 轮)
a0xi0000001aUbfAAE(附加服务)
a0xi0000004ZnehAAC(全市)
a0xi0000001YXcCAAW(鸡尾酒会)

等等等等

【讨论】:

    【解决方案2】:

    您知道每次发出请求时您的 JSon 对象的属性是否都相同吗?不是价值观,只是名字?如果是这样,请创建一个具体类型并使用 JSonObjectSerializer 反序列化为一个对象。如果应该能够在该对象上创建一个字典集合,将您的 JSon 数据反序列化为键值对。然后,您可以像任何其他集合一样通过 Keys 集合进行迭代。

    您实际上并不需要使用动态对象,除非您真的不知道您在输入上处理什么。每次发出请求时,确定您的传入数据是否具有一致的属性名称。

    一个例子可以是

    var myData = JsonSerializer.Deserialize<myDataType>(incomingTextData);
    

    myDataType 会有一个可以处理您的数组的集合。

    【讨论】:

    • 谢谢你的罗斯,我会试一试,告诉你进展如何。据我所知,名称不应该改变,但它们可能会改变的可能性很小。我正在考虑用不同的方法做几个重载方法。
    • 关于 JSON 的好处是它应该反序列化匹配的属性,因此如果发送了一个不完整的 JSON 对象,它会处理它所知道的。
    • 我已经尝试过了,但仍然无法访问 json 数据,请原谅我对此很陌生。我已经添加了我的 json 文件的部分内容
    • 看来您的 JSON 格式不正确。它没有正确反序列化。我假设您粘贴了所有 JSON 数据?
    • 使用jsonutils.com 之类的站点并粘贴数据,它会尝试将其解析为C# 类。如果它成功,你知道你应该能够成功反序列化。
    【解决方案3】:

    这个错误Current JsonReader item is not an Array 是不言自明的:解析的对象不是数组。但是,如果没有看到 Json,我们只能假设这个 Json 是 object,如果你想使用动态对象,请更改代码如下:

    dynamic myJson = JsonConvert.DeserializeObject(File.ReadAllText(@"myfilepath"));
    var currency = myJson.RecordSetBundles[0].Records[0].CurrencyIsoCode
    //Access to other property in your dynamic object
    

    编辑

    您的 JSON 对象似乎很复杂,通过动态访问可能很复杂我建议您使用 JsonConvert.DeserializeObject&lt;T&gt;(string)
    从您发布的 json 中,该类看起来像这样:

    public class Attributes
    {
        public string type { get; set; }
        public string url { get; set; }
    }
    
    public class Record
    {
        public Attributes attributes { get; set; }
        public string CurrencyIsoCode { get; set; }
        public string Id { get; set; }
        public string Name { get; set; }
        public string nihrm__Abbreviation__c { get; set; }
        public string nihrm__AddressLine1__c { get; set; }
        public string nihrm__AlternateNameES__c { get; set; }
        public string nihrm__AvailabilityScreenView__c { get; set; }
        public object nihrm__Geolocation__c { get; set; }
        public bool nihrm__HideBookingsFromPortal__c { get; set; }
        public bool nihrm__IsActive__c { get; set; }
        public bool nihrm__IsPlannerPortalEnabled__c { get; set; }
        public bool nihrm__isRemoveCancelledEventsFromBEOs__c { get; set; }
        public string nihrm__ManagementAffliation__c { get; set; }
        public string nihrm__NearestAirportCode__c { get; set; }
        public string nihrm__Phone__c { get; set; }
        public string nihrm__PostalCode__c { get; set; }
        public string nihrm__PropertyCode__c { get; set; }
        public string nihrm__RegionName__c { get; set; }
        public bool nihrm__RestrictBookingMoveWithPickup__c { get; set; }
        public string nihrm__RohAllowedStatuses__c { get; set; }
        public string nihrm__StateProvince__c { get; set; }
        public string nihrm__SystemOfMeasurement__c { get; set; }
        public string nihrm__TimeZone__c { get; set; }
        public bool nihrm__UpdateBookingEventAverageChecks__c { get; set; }
        public bool nihrm__UseAlternateLanguage__c { get; set; }
        public string nihrm__Website__c { get; set; }
    }
    
    public class RecordSetBundle
    {
        public List<Record> Records { get; set; }
        public string ObjectType { get; set; }
        public bool DeleteFirst { get; set; }
    }
    
    public class RootObject
    {
        public List<RecordSetBundle> RecordSetBundles { get; set; }
    }
    

    使用Newtonsoft反序列化它:

    var myObject = JsonConvert.DeserializeObject<RootObject>(myJsonStrin);
    

    【讨论】:

    • 谢谢 Tinwor,我会试试看的。
    • 我已经尝试过了,但仍然无法访问 json 数据,请原谅我对此很陌生。我已经添加了我的 json 文件的部分内容
    • @NicolePhillips 您是否验证了您的 JSON 以确保它在处理之前没有损坏?
    • @Jay 是的。我用它在salesforce上创建数据,它在那里工作得很好。我需要为我的自动化团队创建它以用于现场验证。
    猜你喜欢
    • 2010-12-19
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2018-09-28
    • 2019-07-02
    • 2023-02-23
    相关资源
    最近更新 更多