0

I am currently consuming JSON output from one source that contains an array and one that does not.

The one with an array is simple, as I can create a class that represents the object and the list of objects, then iterate through the list and get the properties for each object. In the source that does not have an array, however, it is throwing me for a loop.

I do not know how to iterate through this. It seems as if I would need to create separate classes for "abc" and "def" even though the properties of each class are the same. Is there a simple way to do this?

Example that does not contain an array:

    {
"objectContainer": {
    "count": 25,
    "objects": {
        "abc": {
            "name": "object1",
            "parent": "0",
            "status": "0",
        },
        "def": {
            "name": "object2",
            "parent": "0",
            "status": "0",
        }
        etc....

Thanks in advance for any assistance.

3 Answers 3

1

You could use inheritance to prevent repeating the properties for "abc" and "def" over and over again.

public class Base
{
    public string name { get; set; }
    public string parent { get; set; }
    public string status { get; set; }
}

public class Abc : Base { }

public class Def : Base { }

public class Objects
{
    public Abc abc { get; set; }
    public Def def { get; set; }
}

public class ObjectContainer
{
    public int count { get; set; }
    public Objects objects { get; set; }
}

public class RootObject
{
    public ObjectContainer objectContainer { get; set; }
}

Then using JSON.NET you can deserialize the string.

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

The problem is you're going to have to change the code every time you get a new object in there (e.g. ghi).

Another option, particularly if you're going to have different object names showing up, would be to just parse the JSON serially yourself.

JsonTextReader reader = new JsonTextReader( new StringReader( json ) );
while( reader.Read() )
{
    if( reader.Value != null )
    {
        Console.WriteLine( "Field: {0}, Value: {1}", reader.TokenType, reader.Value );
    }
}

Obviously where it's writing output to the Console you'd have to examine the TokenType and Value and stuff those into an object.

Update

This is pretty ugly, but I was curious how I might parse this into the object structure. You'd need to change the receiving object definitions a bit.

public class Base
{
    public string name { get; set; }
    public string parent { get; set; }
    public string status { get; set; }
}

public class Objects
{
    public List<Base> bases { get; set; }

    public Objects()
    {
        bases = new List<Base>();
    }
}

public class ObjectContainer
{
    public int count { get; set; }
    public Objects objects { get; set; }

    public ObjectContainer()
    {
        objects = new Objects();
    }
}

public class RootObject
{
    public ObjectContainer objectContainer { get; set; }

    public RootObject()
    {
        objectContainer = new ObjectContainer();
    }
}

Then you can parse into it using:

while( reader.Read() )
{
    if( reader.Value != null )
    {
        switch( reader.Depth )
        {
            case 2:
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "count" )
                {
                    reader.Read();
                    root.objectContainer.count = Convert.ToInt32( reader.Value );
                }
                break;

            case 3:
                newBase = new Base();
                root.objectContainer.objects.bases.Add( newBase );
                break;

            case 4:
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "name" )
                {
                    reader.Read();
                    newBase.name = reader.Value.ToString();
                }
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "parent" )
                {
                    reader.Read();
                    newBase.parent = reader.Value.ToString();
                }
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "status" )
                {
                    reader.Read();
                    newBase.status = reader.Value.ToString();
                }
                break;
        }
    }
}

Not the prettiest code in the world but as long as the structure of the JSON doesn't change you'll end up with a nice object model no matter how many child objects or what their names are.

Sign up to request clarification or add additional context in comments.

3 Comments

That's what I was afraid of, but I like the inheritance solution to reduce redundancy! However, It simply does not seem like the solution would scale, as the data is subject to change. I'm not sure what the benefit to not having the JSON in an array is, I am new to consuming it.
If the data is going to change then inheritance won't work. You probably can't use the dynamic approach another poster suggested either because you won't know in advance what values you need to grab. I think serial parsing of the content is the best option. At least then you'll have an object model to deal with after you're done. I don't know why the producer would create the JSON like that, it's not something I would have done. You'd have to ask them why they made the choice they did.
Interesting update, I did not think of that. I don't expect the actual structure to change, so it definitely seems like a viable solution. I've contacted the author who published the JSON purely out of curiosity as to why it was formatted in this way. I'll give this a go as an effective solution. Thank you!
0

Based on your JSON above, you would probably need to create classes for those objects. You can abstract some of it away with inheritance as well. If possible, it would make more sense for "objects" to be an array that way you don't need to create separate objects. The name, and implementation both suggest an array.

If you cannot change the structure of the JSON, have a look at the bottom of the page at http://json.org/ for different libraries. Some may be more helpful than others. Json.NET is the one I usually use and you may have better results using something like their JSonReader so you don't have to create an overly complex object structure.

Comments

0

You could use the excellent (and dynamic) JObject class from the JSON.NET library like this:

// example input
var json = @"{""objectContainer"": {
""count"": 25,
""objects"": {
    ""abc"": {
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    },
    ""def"": {
        ""name"": ""object2"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }
}}";

var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
var abc = objectContainer["objects"]["abc"];
Console.WriteLine(abc["name"]);

The output is:

output1

You could even use directly the JObject.Parse() method to load and parse just a JSON code portion (for example if you can extract only the abc part from the complete JSON string):

var abc = JObject.Parse(@"{""abc"": {
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }}")["abc"];
    Console.WriteLine(abc["name"]);

var abcd = JObject.Parse(@"{
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }");
    Console.WriteLine(abcd["name"]);

You could then assign the extracted values to your custom class.

Using the library and the JObject class you don't need to represent the JSON with a class. The downside is, that you don't have the type safety of the class and it's properties.


Update

You could iterate over the properties / objects without knowing their names:

var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
foreach (var o in objectContainer["objects"])
{
    if (o is JProperty)
    {
        var op = ((JProperty)o);
        Console.WriteLine("{0} - {1}", op.Name, op.Value);
    }
}

The output is:

abc - {
"name": "object1",
"parent": "0",
"status": "0"
}
def - {
"name": "object2",
"parent": "0",
"status": "0"
}

2 Comments

I am unfamiliar with the JObject.Parse, I will have to look into that to see if it could be a viable solution. The goal I was trying to accomplish was to iterate through each of the JSON Objects without knowing the names of each object...for example, if "ghi" is added in the future. Thank you for the heads up!
Glad that the answer gave you new ideas. I have updated it and added iteration over elements without knowing their names.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.