【问题标题】:Determine if Json results is object or array判断 Json 结果是对象还是数组
【发布时间】:2013-12-16 20:36:08
【问题描述】:

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

这是我的代码

    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;
    }

上述方法可能不是最好的方法。它就是我现在的位置。

【问题讨论】:

    标签: c# .net json


    【解决方案1】:

    使用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>();
    }
    

    【讨论】:

    • 你可以只检查第一个字符,isArray = content[0] == '['
    • @johnny5 在好的库可用时手动解析通常不是一个好主意。举个例子,你忘了检查空格:) " []" 是一个有效的 json 数组。
    • 这就是为什么我没有将其发布为答案,因为它是一个 hack,但值得一提。
    • 创建 jToken 有多少开销,本质上不是反序列化它吗?
    • @johnny5 “值得注意” - 同意。是的,创建 JToken 基本上是将string 反序列化为Map&lt;string, object&gt;(不需要反射)。但无论如何,OP 已经在反序列化它了。
    【解决方案2】:

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

    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");
    }
    

    用法:

    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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我更喜欢@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}");
      }
      

      【讨论】:

        【解决方案4】:

        如果您使用的是 .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;
               .
               .
               .
            }
        }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-27
          • 2021-02-27
          相关资源
          最近更新 更多