确定Json结果是对象还是数组

dan*_*tch 50 .net c# json

我正在使用.net web api获取json并将其返回到前端以获得角度.json可以是对象或数组.我的代码目前只适用于数组而不是对象.我需要找到一种方法来tryparse或确定内容是对象还是数组.

这是我的代码

    public HttpResponseMessage Get(string id)
    {
        string singleFilePath = String.Format("{0}/../Data/phones/{1}.json", AssemblyDirectory, id);
        List<Phone> phones = new List<Phone>();
        Phone phone = new Phone();
        JsonSerializer serailizer = new JsonSerializer();

        using (StreamReader json = File.OpenText(singleFilePath))
        {
            using (JsonTextReader reader = new JsonTextReader(json))
            {
                //if array do this
                phones = serailizer.Deserialize<List<Phone>>(reader);
                //if object do this
                phone = serailizer.Deserialize<Phone>(reader);
            }
        }

        HttpResponseMessage response = Request.CreateResponse<List<Phone>>(HttpStatusCode.OK, phones);

        return response;
    }
Run Code Online (Sandbox Code Playgroud)

以上可能不是这样做的最佳方式.它就在我现在的位置.

dca*_*tro 115

使用Json.NET,您可以这样做:

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>();
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以检查第一个字符,isArray = content[0] == '[' (2认同)
  • @johnny5 在有好的库可用时手动解析通常不是一个好主意。举个例子,你忘了检查空格:) `" []"` 是一个有效的 json 数组。 (2认同)
  • 这就是为什么我没有把它作为答案发布,因为它是一个黑客,但值得注意. (2认同)

yal*_*lie 9

我发现使用Json.NET 的公认解决方案对于大型 JSON 文件来说有点慢。
该 API 似乎JToken执行了过多的内存分配。
下面是一个使用JsonReaderAPI 的辅助方法,具有相同的结果:

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");
}
Run Code Online (Sandbox Code Playgroud)

用法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Jor*_*dan 6

从美学上来说,我更喜欢@dcastro 给出的答案。但是,如果您要生成 JToken 对象,您也可以仅使用令牌的Type枚举属性。它可能比进行对象类型比较更便宜,因为Type属性已经确定。

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}");
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*819 5

如果您使用的是 .NET Core 3.1,则可以对对象使用以下检查JsonElement

using System.Text.Json;

public void checkJsonElementType(JsonElement element) {
    switch (element.ValueKind)
    {
        case JsonValueKind.Array:
            // it's an array
            // your code in case of array
            break;
        case JsonValueKind.Object:
            // it's an object
            // your code in case of object
            break;
        case JsonValueKind.String:
            // it's an string
            // your code in case of string
            break;
       .
       .
       .
    }
}
Run Code Online (Sandbox Code Playgroud)

JsonValueKind允许的值为Array, False, Null, Number, Object, String, True, Undefined