将JToken(或string)转换为给定的types

TL; DR版本

我有一个JTokentypes的对象(但也可以是一个string ),我需要将其转换为包含在typevariables中的一个types:

 Type type = typeof(DateTime); /* can be any other Type like string, ulong etc */ var obj = jsonObject["date_joined"]; /* contains 2012-08-13T06:01:23Z+05:00 */ var result = Some_Way_To_Convert(type, obj); 

上面的result应该是一个DateTime对象,其值在date_joined给出。

全文

我在Windows Phone项目中同时使用了RestSharp和Json.NET,并且在试图从REST API反序列化JSON响应时被卡住了。

我实际上想要完成的是编写一个通用的方法,可以很容易地将我的JSON响应映射到CLR实体,就像您已经可以使用RestSharp一样。 唯一的问题是,默认的RestSharp实现不适用于我,它不能成功地parsingJSON,因为响应并不总是返回所有的属性(我不返回从REST服务器的null字段)。

这就是为什么我决定使用Newtonsoft的Json.NET,因为它有一个更强大的Json反序列化引擎。 不幸的是,它不支持象RestSharp这样的模糊属性/字段名(或者我还没有find),所以当我使用类似于JsonConvert.DeserializeObject<User>(response.Content)

这是我的Json的样子(实际上是一个例子):

 { "id" : 77239923, "username" : "UzEE", "email" : "uzee@email.net", "name" : "Uzair Sajid", "twitter_screen_name" : "UzEE", "join_date" : "2012-08-13T05:30:23Z05+00", "timezone" : 5.5, "access_token" : { "token" : "nkjanIUI8983nkSj)*#)(kjb@K", "scope" : [ "read", "write", "bake pies" ], "expires" : 57723 }, "friends" : [{ "id" : 2347484", "name" : "Bruce Wayne" }, { "id" : 996236, "name" : "Clark Kent" }] } 

这里是我的CLR实体的一个例子:

 class AccessToken { public string Token { get; set; } public int Expires { get; set; } public string[] Scope { get; set; } public string Secret { get; set; } /* may not always be returned */ } class User { public ulong Id { get; set; } public string UserName { get; set; } public string Email { get; set; } public string Name { get; set; } public string TwitterScreenName { get; set; } public DateTime JoinDate { get; set; } public float Timezone { get; set; } public bool IsOnline { get; set; } /* another field that might be blank eg */ public AccessToken AccessToken { get; set; } public List<User> Friends { get; set; } } 

我想要的是一个简单的方法来parsing上面的JSON到给定的CLR对象。 我查看了RestSharp源代码,并看到了JsonDeserializer代码,我已经能够在JsonDeserializer上编写一个通用的扩展方法DeserializeResponse<T> ,它应该返回一个Ttypes的对象。 预期的用途是这样的:

 var user = JObject.Parse(response.Content).DeserializeResponse<User>(); 

上面的方法应该将给定的Json响应parsing为一个User实体对象。 下面是我在DeserializeResponse<User>扩展方法(基于RestSharp代码)中所做的实际代码片段:

 public static T DeserializeResponse<T>(this JObject obj) where T : new() { T result = new T(); var props = typeof(T).GetProperties().Where(p => p.CanWrite).ToList(); var objectDictionary = obj as IDictionary<string, JToken>; foreach (var prop in props) { var name = prop.Name.GetNameVariants(CultureInfo.CurrentCulture).FirstOrDefault(n => objectDictionary.ContainsKey(n)); var value = name != null ? obj[name] : null; if (value == null) continue; var type = prop.PropertyType; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { type = type.GetGenericArguments()[0]; } // This is a problem. I need a way to convert JToken value into an object of Type type prop.SetValue(result, ConvertValue(type, value), null); } return result; } 

我猜测这个转换应该是一个非常简单的事情,因为这个任务很简单。 但是我一直在寻找一个相当长的一段时间,仍然没有find一种方法来通过Json.NET来做到这一点(老实说,尽pipe理解和缺乏一些例子,文档还是挺有用的)。

任何帮助真的不胜感激。

现在有一个ToObject方法。

 var obj = jsonObject["date_joined"]; var result = obj.ToObject<DateTime>(); 

它也适用于任何复杂types,并遵守JsonPropertyAttribute规则

 var result = obj.ToObject<MyClass>(); public class MyClass { [JsonProperty("date_field")] public DateTime MyDate {get;set;} } 
 System.Convert.ChangeType(jtoken.ToString(), targetType); 

要么

 JsonConvert.DeserializeObject(jtoken.ToString(), targetType); 

– 编辑 –

Uzair,这是一个完整的例子,只是为了向你展示他们的工作

 string json = @"{ ""id"" : 77239923, ""username"" : ""UzEE"", ""email"" : ""uzee@email.net"", ""name"" : ""Uzair Sajid"", ""twitter_screen_name"" : ""UzEE"", ""join_date"" : ""2012-08-13T05:30:23Z05+00"", ""timezone"" : 5.5, ""access_token"" : { ""token"" : ""nkjanIUI8983nkSj)*#)(kjb@K"", ""scope"" : [ ""read"", ""write"", ""bake pies"" ], ""expires"" : 57723 }, ""friends"" : [{ ""id"" : 2347484, ""name"" : ""Bruce Wayne"" }, { ""id"" : 996236, ""name"" : ""Clark Kent"" }] }"; var obj = (JObject)JsonConvert.DeserializeObject(json); Type type = typeof(int); var i1 = System.Convert.ChangeType(obj["id"].ToString(), type); var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type); 
 var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type); 

抛出一个parsingexception,因为第一个参数(我认为)周围缺less引号。 我通过添加引号使其工作:

 var i2 = JsonConvert.DeserializeObject("\"" + obj["id"].ToString() + "\"", type); 

我能够使用下面的方法为我的WebAPI转换:

 [HttpPost] public HttpResponseMessage Post(dynamic item) // Passing parameter as dynamic { JArray itemArray = item["Region"]; // You need to add JSON.NET library JObject obj = itemArray[0] as JObject; // Converting from JArray to JObject Region objRegion = obj.ToObject<Region>(); // Converting to Region object }