Reputation: 763
I am trying to read in a json file which is very complex into a JArray that can be accessed dynamically in a foreach statement. However I am getting an error which is stating 'Current JsonReader item is not an Array' I am able to access the keys and values if I use a JObject but that is not what I need I need to be able to go through the records and search by names or IDs, etc. I am a bit new at newtwonsoft and JSON.net so any help would be appreciated!
JArray o1 = JArray.Parse(File.ReadAllText(@"myfilepath"));
dynamic records = o1;
foreach (dynamic record in records)
{
Console.WriteLine(record.Id + " (" + record.Name + ")");
}
My json file looks like this, there are multiple records however I have shortened it. I need to access and search by Id or Name however I am having issues accessing.
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
},
Here is a link to the entire json: https://codeshare.io/rGL6K5
Upvotes: 1
Views: 5401
Reputation: 8194
The other answers show strong typed classes. If you can do this and you're sure the structure won't change I'd recommend doing it that way. It'll make everything else much easier.
If you want to do it with a dynamic object, then you can get what you want this way.
// 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() + ")");
}
}
Produces this output:
a0di0000001nI3oAAE (The City Hotel)
a0xi0000000jOQCAA2 (Rounds of 8)
a0xi0000001aUbfAAE (Additional Services)
a0xi0000004ZnehAAC (Citywide)
a0xi0000001YXcCAAW (Cocktail Rounds)
etc etc
Upvotes: 1
Reputation: 7973
This error Current JsonReader item is not an Array
is self explanatory: the object parsed is not an array.However without see the Json we can only suppose that this Json is an object
and if you want use a dynamic object change the code as follow:
dynamic myJson = JsonConvert.DeserializeObject(File.ReadAllText(@"myfilepath"));
var currency = myJson.RecordSetBundles[0].Records[0].CurrencyIsoCode
//Access to other property in your dynamic object
EDIT
Your JSON object seems quite complex and access via dynamic can be complex I suggest you to use JsonConvert.DeserializeObject<T>(string)
.
From the json that yoou have posted the class looks like this:
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; }
}
To deserialize it using Newtonsoft
:
var myObject = JsonConvert.DeserializeObject<RootObject>(myJsonStrin);
Upvotes: 1
Reputation: 646
Do you know if the properties of your JSon object will be the same each time the request is made? Not the values, just the names? If so, create a concrete type and use JSonObjectSerializer to deserialize into an object. If should be able to create a dictionary collection on that object that deserialized your JSon data into Key Value pairs. Then you can iterate like any other collection via the Keys collection.
You don't really need to use dynamic objects unless you really don't know what you are dealing with on the input. Ascertain if your incoming data has consistent property names each time the request is made.
An example could be
var myData = JsonSerializer.Deserialize<myDataType>(incomingTextData);
myDataType would have a collection that can handle your array.
Upvotes: 1