我的项目包含过多的对rest api的调用,有时我得到json数组和有时json对象。
当前,我必须为每个调用编写相同的重复代码,以确定响应json是数组还是对象。
所以我遇到以下错误,因为我不知道传入的json类型。
无法将当前JSON数组(例如[1,2,3])反序列化为类型'userList',因为该类型需要JSON对象(例如{“ name”:“ value”})才能正确反序列化。要解决此错误,可以将JSON更改为JSON对象(例如{“ name”:“ value”}),也可以将反序列化类型更改为数组,或者将实现集合接口的类型(例如ICollection,IList)更改为List,例如List从JSON数组反序列化。还可以将JsonArrayAttribute添加到该类型中,以强制其从JSON数组反序列化
OR
无法将当前JSON对象(例如{“ name”:“ value”})反序列化为类型'System.Collections.Generic.List`1 [MvcSumit1.Models.User]',因为该类型需要JSON数组(例如[1,2,3])正确反序列化。要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化类型,使其成为普通的.NET类型(例如,不像整数这样的原始类型,也不像这样的集合类型数组或列表),可以从JSON对象反序列化。还可以将JsonObjectAttribute添加到类型中,以强制其从JSON对象反序列化。
因此,要摆脱这个问题,我想要可以同时处理上述两种情况的通用方法。
答案 0 :(得分:2)
我想要可以处理以上两种情况的通用方法。
下面的通用方法可以将传入的json解析为object
或List<object>
。
public class Utility
{
public static object JsonParser<T>(string json)
{
try
{
JToken jToken = JToken.Parse(json);
if (jToken is JArray)
return jToken.ToObject<List<T>>();
else if (jToken is JObject)
return jToken.ToObject<T>();
else
return "Unable to cast json to unknown type";
}
catch (JsonReaderException jex)
{
return jex.Message;
}
catch (Exception ex)
{
return ex.Message;
}
}
}
您可以使用上述通用方法,如下所示。我创建了一个控制台应用程序供您演示。
class Program
{
static void Main(string[] args)
{
var result = Utility.JsonParser<User>("You json either object or array");
if (result is List<User>)
{
var userList = result as List<User>;
userList.ForEach(user => Console.WriteLine($"Id: {user.Id}, Name: {user.Name}, Age: {user.Age}"));
}
else if (result is User)
{
var user = result as User;
Console.WriteLine($"Id: {user.Id}, Name: {user.Name}, Age: {user.Age}");
}
else if (result is string)
{
Console.WriteLine(result);
}
Console.ReadLine();
}
}
样本类用于反序列化您的json。
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
输出:
1)通过将json与对象数组结合使用
string json1 = @"[{'Id':'1','Name':'Mike','Age':43},{'Id':'2','Name':'Anna','Age':56}]";
2)通过仅将json与对象配合使用。
string json2 = @"{'Id':'3','Name':'John','Age':24}";
替代
下面的通用方法可以将传入的json解析为object
或List<object>
并返回List<object>
。
public class Utility
{
public static List<T> JsonParser<T>(string json)
{
JToken jToken = JToken.Parse(json);
if (jToken is JArray)
{
return jToken.ToObject<List<T>>();
}
else if (jToken is JObject)
{
List<T> lst = new List<T>();
lst.Add(jToken.ToObject<T>());
return lst;
}
else
return new List<T>();
}
}
您可以使用上述通用方法,如下所示。
class Program
{
static void Main(string[] args)
{
var userList = Utility.JsonParser<User>("You json either object or array");
if (userList.Count > 0)
{
userList.ForEach(user => Console.WriteLine($"Id: {user.Id}, Name: {user.Name}, Age: {user.Age}"));
}
else
{
//Do code here if your list is empty
}
Console.ReadLine();
}
}
答案 1 :(得分:0)
如果我们不仅要用Array
或object
来处理不同的类型,下面是我的方法:
(请注意我是using Newtonsoft.Json
)
方法1
public bool TryDeserialize(string json, out object target, params Type[] types)
{
foreach (Type type in types)
{
try
{
target = JsonConvert.DeserializeObject(json, type);
return true;
}
catch (Exception)
{
}
}
target = null;
return false;
}
然后按以下方式使用它:
object obj = null;
Type[] types = new Type[] { typeof(TypeA), typeof(List<TypeB>) };
if (TryDeserialize(json, out obj, types))
{
if (obj is TypeA)
{
var r = obj as TypeA;
}
else
{
var r = obj as List<TypeB>;
}
}
或方法2
public bool TryDeserialize<T1, T2>(string json, out object target)
{
try
{
target = JsonConvert.DeserializeObject<T1>(json);
return true;
}
catch (Exception)
{
}
try
{
target = JsonConvert.DeserializeObject<T2>(json);
return true;
}
catch (Exception)
{
target = null;
return false;
}
}
并像这样使用它:
object obj = null;
if (TryDeserialize<TypeA, List<TypeB>>(json, out obj))
{
if (obj is TypeA)
{
var r = obj as TypeA;
}
else
{
var r = obj as List<TypeB>;
}
}