【问题标题】:JSON value is sometimes a string and sometimes an objectJSON 值有时是字符串,有时是对象
【发布时间】:2016-06-21 19:34:04
【问题描述】:

我有一些可以有两种不同格式的 JSON。有时location 值是一个字符串,有时它是一个对象。这是第一种格式的示例:

{
  "result": [
    {
      "upon_approval": "Proceed to Next Task",
      "location": "",
      "expected_start": ""
    }
  ]
}

为此的类定义:

public class Result
{
    public string upon_approval { get; set; }
    public string location { get; set; }
    public string expected_start { get; set; }
}

public class RootObject
{
    public List<Result> result { get; set; }
}

这是第二种格式的 JSON:

{
  "result": [
    {
      "upon_approval": "Proceed to Next Task",
      "location": {
        "display_value": "Corp-HQR",
        "link": "https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090"
      },
      "expected_start": ""
    }
  ]
}

为此的类定义:

public class Location
{
    public string display_value { get; set; }
    public string link { get; set; }
}

public class Result
{
    public string upon_approval { get; set; }
    public Location location { get; set; }
    public string expected_start { get; set; }
}

public class RootObject
{
    public List<Result> result { get; set; }
}

在反序列化时,如果 JSON 格式与我的类不匹配,我会收到错误消息,但我不知道要使用哪些类,因为 JSON 格式会发生变化。那么如何动态地让这两种 JSON 格式反序列化为一组类呢?

这就是我现在反序列化的方式:

JavaScriptSerializer ser = new JavaScriptSerializer();
ser.MaxJsonLength = 2147483647;
RootObject ro = ser.Deserialize<RootObject>(responseValue);

【问题讨论】:

  • 你的“结果”数组可以同时包含它们吗?
  • @Eser 不,我只能包含它们的任一类定义,但 json 响应具有字符串或类。所以我不知道如何忽略这些字符串值。
  • This可以给你一个提示......

标签: c# json javascriptserializer


【解决方案1】:

要解决这个问题,您需要创建一个自定义 JavaScriptConverter 类并将其注册到序列化程序。序列化器会将result 数据加载到Dictionary&lt;string, object&gt; 中,然后交给转换器,您可以在其中检查内容并将其转换为可用对象。简而言之,这将允许您将第二组类用于两种 JSON 格式。

这是转换器的代码:

class ResultConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new List<Type> { typeof(Result) }; }
    }

    public override object Deserialize(IDictionary<string, object> dict, Type type, JavaScriptSerializer serializer)
    {
        Result result = new Result();
        result.upon_approval = GetValue<string>(dict, "upon_approval");
        var locDict = GetValue<IDictionary<string, object>>(dict, "location");
        if (locDict != null)
        {
            Location loc = new Location();
            loc.display_value = GetValue<string>(locDict, "display_value");
            loc.link = GetValue<string>(locDict, "link");
            result.location = loc;
        }
        result.expected_start = GetValue<string>(dict, "expected_start");
        return result;
    }

    private T GetValue<T>(IDictionary<string, object> dict, string key)
    {
        object value = null;
        dict.TryGetValue(key, out value);
        return value != null && typeof(T).IsAssignableFrom(value.GetType()) ? (T)value : default(T);
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后像这样使用它:

var ser = new JavaScriptSerializer();
ser.MaxJsonLength = 2147483647;
ser.RegisterConverters(new List<JavaScriptConverter> { new ResultConverter() });
RootObject ro = serializer.Deserialize<RootObject>(responseValue);

这是一个简短的演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
          ""result"": [
            {
              ""upon_approval"": ""Proceed to Next Task"",
              ""location"": {
                ""display_value"": ""Corp-HQR"",
                ""link"": ""https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090""
              },
              ""expected_start"": """"
            }
          ]
        }";

        DeserializeAndDump(json);
        Console.WriteLine(new string('-', 40));

        json = @"
        {
          ""result"": [
            {
              ""upon_approval"": ""Proceed to Next Task"",
              ""location"": """",
              ""expected_start"": """"
            }
          ]
        }";

        DeserializeAndDump(json);

    }

    private static void DeserializeAndDump(string json)
    {
        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new List<JavaScriptConverter> { new ResultConverter() });
        RootObject obj = serializer.Deserialize<RootObject>(json);

        foreach (var result in obj.result)
        {
            Console.WriteLine("upon_approval: " + result.upon_approval);
            if (result.location != null)
            {
                Console.WriteLine("location display_value: " + result.location.display_value);
                Console.WriteLine("location link: " + result.location.link);
            }
            else
                Console.WriteLine("(no location)");
        }
    }
}

public class RootObject
{
    public List<Result> result { get; set; }
}

public class Result
{
    public string upon_approval { get; set; }
    public Location location { get; set; }
    public string expected_start { get; set; }
}

public class Location
{
    public string display_value { get; set; }
    public string link { get; set; }
}

输出:

upon_approval: Proceed to Next Task
location display_value: Corp-HQR
location link: https://satellite.service-now.com/api/now/table/cmn_location/4a2cf91b13f2de00322dd4a76144b090
----------------------------------------
upon_approval: Proceed to Next Task
(no location)

【讨论】:

  • 谢谢布赖恩,这很有帮助。你让我的工作变得如此轻松。我现在欠你太多了。
  • 不用担心;很高兴我能提供帮助。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
相关资源
最近更新 更多