2

Hey all I am in need of some help with looping through the following JSON string:

{
  "application_uid" : "3912d337-b797-4508-8c95-c76df8888ada",
  "formId" : "F_Form1",
  "recordCount" : 1,
  "items" :
    [
        {
    "lastModified" : "2015-12-11T20:07:25.774Z",
    "lastModifiedBy" :
      {
        "displayName" : "Anonymous Guest User",
        "email" : "",
        "login" : "Anonymous Guest User"
      },
    "created" : "2015-12-11T20:07:25.774Z",
    "createdBy" :
      {
        "displayName" : "Anonymous Guest User",
        "email" : "",
        "login" : "Anonymous Guest User"
      },
    "draft_ownerid" : "",
    "flowState" : "ST_End",
    "id" : 20,
    "uid" : "5928bb18-5b53-43f9-8831-baab042e1ca2",
    "F_ReceivedYorN" : "Y",
    "F_ContractNumber" : "5556420121",
    "F_FileNumber" : "0630250",
    "F_SubscriberLastName" : "JEFFERY",
    etc etc...

Problem being is that the names can change F_ReceivedYorN, F_ContractNumber, F_FileNumber, etc.

I know how to get the value via looping but only with defining the name of the object. The only names that will stay static no matter what are the flowState, id and uid values.

How can I loop though each of the names even though I do not know what they are going to be called?

UPDATE

The supposed solution does not help as its not like my example above. REOPEN

StealthRT
  • 10,108
  • 40
  • 183
  • 342
  • Is there a fixed list of names that the fields can be? How do you identify that you've selected the correct data if the name keeps changing? – Mr. Llama Mar 07 '16 at 17:08
  • @Mr.Llama What I am just looking for is the name and value. I am able to get a list of the names from another API pull and can match that name with the ones in this one. – StealthRT Mar 07 '16 at 17:16
  • You can use [`[JsonExtensionData]`](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonExtensionDataAttribute.htm). See [Deserialize json with known and unknown fields](https://stackoverflow.com/questions/15253875) or [Deserialize part of JSON object and serialize it back with the remaining properties intact](https://stackoverflow.com/questions/26937606) – dbc Mar 07 '16 at 17:41
  • Possible duplicate of [Deserialize json with known and unknown fields](http://stackoverflow.com/questions/15253875/deserialize-json-with-known-and-unknown-fields) – dbc Mar 07 '16 at 17:41

1 Answers1

1

Your JSON consists of a root object that contains a "items" property that has an array of objects with both standard and variable properties. You need to capture all the property names and values in each item without knowing them in advance.

You've tagged your question so I'll answer in c#. You have a couple of options.

Use [JsonExtensionData]

Json.NET supports deserialization and re-serialization of arbitrary JSON properties into a POCO by adding [JsonExtensionData] to a dictionary of custom property name/value pairs:

public class Item
{
    public Item() { this.CustomFields = new Dictionary<string, JToken>(); }

    public string flowState { get; set; }
    public long id { get; set; }
    public Guid uid { get; set; }

    [JsonExtensionData]
    public IDictionary<string, JToken> CustomFields { get; private set; }
}

public class RootObject
{
    public RootObject() { this.items = new List<Item>(); }

    public Guid application_uid { get; set; }
    public string formId { get; set; }
    public int recordCount { get; set; }
    public List<Item> items { get; set; }
}

Then you can loop through the names and values of the custom properties as follows:

        var root = JsonConvert.DeserializeObject<RootObject>(json);

        foreach (var item in root.items)
        {
            Console.WriteLine(string.Format("Showing custom properties for Item id {0}, uid {1}, flowState {2}", item.id, item.uid, item.flowState));
            {
                foreach (var field in item.CustomFields)
                {
                    Console.WriteLine(string.Format("    Field: \"{0}\": Value: \"{1}\"", field.Key, field.Value.ToString(Formatting.None)));
                }
                Console.WriteLine("");
            }
        }

Prototype fiddle.

Use ExpandoObject

Json.NET directly supports deserializing to ExpandoObject so you could use this class for your item:

public class RootObject
{
    public RootObject() { this.items = new List<ExpandoObject>(); }

    public Guid application_uid { get; set; }
    public string formId { get; set; }
    public int recordCount { get; set; }
    public List<ExpandoObject> items { get; set; }
}

Then do:

        var root = JsonConvert.DeserializeObject<RootObject>(json);

        foreach (var item in root.items)
        {
            Console.WriteLine(string.Format("Showing custom properties for Item id {0}, uid {1}, flowState \"{2}\":", 
                                            item.AsDynamic().id, item.AsDynamic().uid, item.AsDynamic().flowState));
            {
                foreach (var field in item.AsDictionary())
                {
                    if (field.Key == "id" || field.Key == "uid" || field.Key == "flowState")
                        continue;                       
                    Console.WriteLine(string.Format("  - Field: \"{0}\":\n    Value: {1}", field.Key, JsonConvert.SerializeObject(field.Value)));
                }
                Console.WriteLine("");
            }
        }

With the following extension methods:

public static class DictionaryExtensions
{
    public static IDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
    {
        return dictionary;
    }
}

public static class DynamicExtensions
{
    public static dynamic AsDynamic(this IDynamicMetaObjectProvider obj)
    {
        return obj;
    }
}

Prototype fiddle.

This removes the direct dependency on Json.NET from your models. However, unlike the first solution, ExpandoObject is sealed so cannot be subclassed to add your standard three properties.

dbc
  • 104,963
  • 20
  • 228
  • 340