将JSON文件读入Jarray并动态访问数据

时间:2016-11-09 14:44:29

标签: c# arrays json.net

我正在尝试读取一个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或Name访问和搜索,但我遇到了访问问题。

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

3 个答案:

答案 0 :(得分:1)

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

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

一个例子可能是

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

myDataType将有一个可以处理你的数组的集合。

答案 1 :(得分:1)

此错误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<T>(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);

答案 2 :(得分: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(Cocktail Rounds)

等等