5

sorry folks. I'm pretty new to writing code...

I'm writing a powershell cmdlet in c# and it reaches out to an API and gets JSON as a response.

Depending on the call I make to an API, a JSON array or a single JSON object is returned

Sometiems, it can be

{"result": [
{
"id": "24095",
"hostid": "24094",
"name": "host1.fqdn.com",
"clustered": "false",
"type": "VM",
"ipaddress" : "192.168.1.184"
},
{
"id": "24097",
"hostid": "24096",
"name": "host2.fqdn.com",
"clustered": "true",
"type": "VM",
"ipaddress" : "192.168.1.185"
}
]
}

and sometimes it can be

{"result": {
"id": "24095",
"hostid": "24094",
"name": "host1.fqdn.com",
"clustered": "false",
"type": "VM",
"ipaddress" : "192.168.1.184"
}
}

I'm trying to figure out how using JSON.NET, i can figure out if the json returned has an object for "result" or an array for "result".

Based on the check,I'd like to call a method that prints out the object or array in a CSV format

I'm hoping to write a generic method that will print out all the keys as the CSV header and the values as rows for the CSV.

But the first thing I'm having trouble with is figuring out whether my JSON object has an Array or just an Object

I tried

JObject jsonres = JObject.Parse(strResponse);
JObject appobj = (JObject)jsonres.SelectToken("result");

Console.WriteLine(appobj.Type.ToString());

results in

Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'Newtonsoft.Json.Linq.JObject'.

when appobj["result"] is an array and works just fine and prints "Object" when appobj["result"] is a single object.

4 Answers 4

7

Not sure if this the optimum way to handle it, but you could use something like this:

if ( jsonres.SelectToken("result") is JObject )
{ ... }
else if ( jsonres.SelectToken("result") is JArray)
{ ... }
else
{ ...some exception perhaps }

Edit: Slight improvisation

if ( jsonres.SelectToken("result") is JObject )
{ //Create JArray with the lone "result" in it }

//Use the JArray 
Sign up to request clarification or add additional context in comments.

1 Comment

Oh! Sweet! That makes it a whole lot easier! Thank you very much @bit.
4

This will work:

   JObject jsonres = JObject.Parse(json);
   Console.WriteLine(jsonres["result"].Type);

To find out whether it's an Object or Array. You can use a switch-case on the enum:

            switch(jsonres["result"].Type)
            {
                case JTokenType.Object:
               //Do something if it's an object
                    break;
                case JTokenType.Array:
                //Do something if it's an array
                    break;
            }

1 Comment

Thank you. This is also a great alternative!
2

This is quite an old question, but I've got an answer for the System.Text.Json namespace in case you do not want to use the Newtonsoft.Json namesapce. There is also a Parse method within JsonDocument where you can determine the class of the root element.

var JDocument = System.Text.Json.JsonDocument.Parse(json);
if (JDocument.RootElement.ValueKind == JsonValueKind.Object)
{
    //Object
}

if (JDocument.RootElement.ValueKind == JsonValueKind.Array)
{
    //Array or List
}

Comments

0

You could create JsonConverter for that e.g.

public class SingleOrListJsonConverter : JsonConverter
{
    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.ReadFrom(reader);
        switch (token.Type)
        {
            case JTokenType.Object:
                var item = token.ToObject<MyResultType>();
                return new List<MyResultType>(new[] {item});
            case JTokenType.Array:
                return token.ToObject<List<MyResultType>>();
            default:
                return new List<MyResultType>();
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<MyResultType>) || objectType == typeof(MyResultType);
    }
}

and then just decorate your property with this converter

public class MyClass
{
    [TypeConverter(typeof(SingleOrListJsonConverter))]
    public MyResultType Result { get; set; }
}

I guess we could even make this converter generic, but this is just a simple example.

Comments

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.