【问题标题】:Force conversion of empty JSON array to Dictionary type强制将空 JSON 数组转换为 Dictionary 类型
【发布时间】:2014-12-30 18:03:32
【问题描述】:

问题是,PHP 中的json_encode() 函数为读取其输出的工具留下了歧义。在 PHP 中,列表和字典都是同一类型的 array

echo json_encode([]); // []
echo json_encode(["5" => "something"]); // {"5": "something"}

在 JSON.NET 中,我想强制 []{"5": "something"} 转换为 Dictionary<string, string> 类型。但是,它将 [] 识别为 Dictionary 的禁止结构并引发异常。

我可以快速将空的 JSON 数组保留为空或强制它们转换为空的 Dictionary 类型吗?

最终解决方案

我修改了接受的答案,使其通用且可重复用于其他类型。

public class DictionaryOrEmptyArrayConverter<T,F> : JsonConverter
{
    public override bool CanWrite { get { return false; } }
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Dictionary<T, F>);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case JsonToken.StartArray:
                reader.Read();
                if (reader.TokenType == JsonToken.EndArray)
                    return new Dictionary<T, F>();
                else
                    throw new JsonSerializationException("Non-empty JSON array does not make a valid Dictionary!");
            case JsonToken.Null:
                return null;
            case JsonToken.StartObject:
                var tw = new System.IO.StringWriter();
                var writer = new JsonTextWriter(tw);
                writer.WriteStartObject();
                int initialDepth = reader.Depth;
                while (reader.Read() && reader.Depth > initialDepth)
                {
                    writer.WriteToken(reader);
                }
                writer.WriteEndObject();
                writer.Flush();
                return JsonConvert.DeserializeObject<Dictionary<T, F>>(tw.ToString());
            default:
                throw new JsonSerializationException("Unexpected token!");
        }
    }

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

您应该将它与您的 JSON 对象一起使用,如下例所示:

public class Company
{
    public string industry_name { get; set; }

    [JsonConverter(typeof(DictionaryOrEmptyArrayConverter<int, Upgrade>))]
    public Dictionary<int, Upgrade> upgrades { get; set; }
}

public class Upgrade
{
    public int level { get; set; }
}

它允许您使用DeserializeObject 方法快速将JSON字符串转换为对象:

var result = JsonConvert.DeserializeObject<Company>(jsonString);

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    或者您可以通过删除所有这些空数组属性来预处理 json 文本。

    //Will not work with formatted json due to whitespace    
    json = Regex.Replace(json, ",?\"[^\"]+\":[[]]", "");
    

    【讨论】:

      【解决方案2】:

      您可以使用自定义 JsonConverter 来完成此操作,但我认为此解决方案还有一些不足之处:

          private class DictionaryConverter : JsonConverter
          {
              public override bool CanWrite { get { return false; } }
              public override bool CanConvert(Type objectType)
              {
                  return objectType == typeof(Dictionary<string, string>);
              }
              public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
              {
                  if (reader.TokenType == JsonToken.StartArray)
                  {
                      reader.Read();
                      if (reader.TokenType == JsonToken.EndArray)
                          return new Dictionary<string, string>();
                      else
                          throw new JsonSerializationException("Non-empty JSON array does not make a valid Dictionary!");
                  }
                  else if (reader.TokenType == JsonToken.Null)
                  {
                      return null;
                  }
                  else if (reader.TokenType == JsonToken.StartObject)
                  {
                      Dictionary<string, string> ret = new Dictionary<string, string>();
                      reader.Read();
                      while (reader.TokenType != JsonToken.EndObject)
                      {
                          if (reader.TokenType != JsonToken.PropertyName)
                              throw new JsonSerializationException("Unexpected token!");
                          string key = (string)reader.Value;
                          reader.Read();
                          if (reader.TokenType != JsonToken.String)
                              throw new JsonSerializationException("Unexpected token!");
                          string value = (string)reader.Value;
                          ret.Add(key, value);
                          reader.Read();
                      }
                      return ret;
                  }
                  else
                  {
                      throw new JsonSerializationException("Unexpected token!");
                  }
              }
      
              public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
              {
                  throw new NotImplementedException();
              }
          }
      

      https://dotnetfiddle.net/zzlzH4查看此代码的运行情况

      【讨论】:

        猜你喜欢
        • 2019-03-23
        • 1970-01-01
        • 2016-03-18
        • 2014-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多