我有一些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);
答案 0 :(得分:2)
要解决此问题,您需要创建一个自定义JavaScriptConverter
类并将其注册到序列化程序。序列化器将result
数据加载到Dictionary<string, object>
,然后切换到转换器,您可以在其中检查内容并将其转换为可用对象。简而言之,这将允许您将第二组类用于两种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)