【问题标题】:Deserializing list of JSON objects in WebApi method在 WebApi 方法中反序列化 JSON 对象列表
【发布时间】:2013-04-05 18:47:44
【问题描述】:

我正在尝试研究如何从 WEBAPI 调用中的 JSON 请求中提取对象列表。在这个对象列表中有一个 Dictionary 对象、一个 List 对象和一个 List> 对象。

我的 MVC 控制器的请求看起来有点像这样:

//Gets a list of various objects
List<object> values = new List<object>(); 
values.add(GetItem1()); //Returns a Dictionary<string, string> object
values.add(GetItem2()); //Returns a List<string> object
values.add(GetItem3()); //List<KeyValuePair<string, string>> 

var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;

在 WEBAPI 对象中,我有这个函数接收来自 MVC 控制器的调用。这是我遇到麻烦的地方,我无法将数据从列表中取出。列表中的第一项恰好是字典。

[HttpPost]
public void LogError(List<object> myObjectList)
{
    Dictionary<string, string> items = (Dictionary<string, string>)myObjectList[0];
    List<string> moreItems = (List<string>)myObjectList[1];
    List<KeyValuePair<string, string>> evenMoreItems = (List<KeyValuePair<string, string>>)myObjectList[2];
}

如果我尝试开始使用该对象,则会收到错误消息:

Cannot cast 'myObjectList[0]' (which has an actual type of 'Newtonsoft.Json.Linq.JObject') to 'System.Collections.Generic.Dictionary<string,string>'

不幸的是,我完全不知道下一步该做什么。我似乎找不到将 List 反序列化为这些单独对象类型的方法。

【问题讨论】:

    标签: json serialization asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    您遇到强制转换异常的原因是客户端和服务器丢失了类型信息。

    让您的方案发挥作用的一种方法是执行以下操作

    1. 使用 ObjectContent 代替 StringContent 所以我们让格式化程序(即 JsonMediaTypeFormatter)来处理序列化和反序列化
    2. 在客户端和服务器上都打开 TypeNameHandling,以便通过网络发送类型信息

    服务器(WebApiConfig.cs):

     config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;
    

    客户:

            //Gets a list of various objects
            List<object> values = new List<object>();
            values.Add(GetItem1()); //Returns a Dictionary<string, string> object
            values.Add(GetItem2()); //Returns a List<string> object
            values.Add(GetItem3()); //List<KeyValuePair<string, string>> 
    
            var formatter = new JsonMediaTypeFormatter();
            formatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;
    
            var content = new ObjectContent<List<object>>(values, formatter);
            HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;
    

    示例请求正文:

    {"$type":"System.Collections.Generic.List1[[System.Object, mscorlib]], mscorlib","$values":[{"$type":"System.Collections.Generic.Dictionary2[[System.String, mscorlib],[System.String, mscorlib]], mscorlib","DictionaryKey1":"DictionaryValue1"},{"$type":"System.Collections.Generic.List1[[System.String, mscorlib]], mscorlib","$values":["ListItem1"]},{"$type":"System.Collections.Generic.List1[[System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib],[System.String, mscorlib]], mscorlib]], mscorlib","$values":[{"Key":"KeyValuePairKey","Value":"KeyValuePairKeyValue"}]}]}

    【讨论】:

    • 谢谢!这成功了。我确实必须添加一个反序列化步骤。这是一些示例代码: Dictionary parameters = JsonConvert.DeserializeObject>(convertedObjectList[0].ToString());
    【解决方案2】:

    我可能错了,但我想你不能有一个

    列表[对象]

    它如何知道类型是什么?您需要指定传入类型的具体对象吗?

    从简单的开始:

    public class TestClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    列表值 = new List(); values.Add(new TestClass() { Id = 1, Name = "test1" }); values.Add(new TestClass() { Id = 12, Name = "test2" });

    var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
    HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;
    

    接收webapi方法:

    public void LogError(List<TestObject> myObjectList)
    { // breakpoint here and see what myObjectList contains
    
    }
    

    【讨论】:

    • 好吧,当我调试 WEPAPI 时,我可以看到所有的数据,而且一切看起来都差不多:但是当我尝试转换它时,(参见第二个代码块),一切都崩溃了.这就是我卡住的地方
    • 我认为您可能很难直接将其转换为字典,您可能必须遍历列表并自己重新填充字典。
    • 你试过用 Dictionary 作为控制器方法的参数吗?
    • 为了清楚起见,对象列表中有各种不同的对象(不要问)。第一个是 Dictionary 类型,第二个是 list,第三个是 List> 对象。
    • 怀疑它能否解决这个问题。我认为您最好将它们包装到一个类中,然后将该类定义为方法参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 2014-08-04
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多