Determine if Json results is object or array

前端 未结 3 1954
借酒劲吻你
借酒劲吻你 2020-12-05 06:02

I am using .net web api to get json and return it to the front end for angular. The json can be either an object or an array. My code currently only works for the array not

相关标签:
3条回答
  • 2020-12-05 06:44

    Using Json.NET, you could do this:

    string content = File.ReadAllText(path);
    var token = JToken.Parse(content);
    
    if (token is JArray)
    {
        IEnumerable<Phone> phones = token.ToObject<List<Phone>>();
    }
    else if (token is JObject)
    {
        Phone phone = token.ToObject<Phone>();
    }
    
    0 讨论(0)
  • 2020-12-05 06:46

    I found that the accepted solution using Json.NET is a bit slow for large JSON files.
    Looks like JToken API is doing too much memory allocations.
    Here is a helper method that uses JsonReader API to do the same:

    public static List<T> DeserializeSingleOrList<T>(JsonReader jsonReader)
    {
        if (jsonReader.Read())
        {
            switch (jsonReader.TokenType)
            {
                case JsonToken.StartArray:
                    return new JsonSerializer().Deserialize<List<T>>(jsonReader);
    
                case JsonToken.StartObject:
                    var instance = new JsonSerializer().Deserialize<T>(jsonReader);
                    return new List<T> { instance };
            }
        }
    
        throw new InvalidOperationException("Unexpected JSON input");
    }
    

    The usage:

    public HttpResponseMessage Get(string id)
    {
        var filePath = $"{AssemblyDirectory}/../Data/phones/{id}.json";
    
        using (var json = File.OpenText(filePath))
        using (var reader = new JsonTextReader(json))
        {
            var phones = DeserializeSingleOrList<Phone>(reader);
    
            return Request.CreateResponse<List<Phone>>(HttpStatusCode.OK, phones);
        }
    }
    
    0 讨论(0)
  • 2020-12-05 06:50

    Asthetically I like the answer @dcastro gave better. But, if you are generating a JToken object, you can also just use the Type enum property of the token. It's possibly less expensive then doing an object type comparison, as the Type property has already been determined.

    https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htm

    //...JToken token
    if (token.Type == JTokenType.Array)
    {
        IEnumerable<Phone> phones = token.ToObject<List<Phone>>();
    }
    else if (token.Type == JTokenType.Object)
    {
        Phone phone = token.ToObject<Phone>();
    }
    else
    {
        Console.WriteLine($"Neither, it's actually a {token.Type}");
    }
    
    0 讨论(0)
提交回复
热议问题