【发布时间】:2012-08-09 06:13:16
【问题描述】:
TL;DR 版本
我有一个JToken 类型的对象(但也可以是string),我需要将其转换为包含在type 变量中的类型:
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 实现对我不起作用,它无法成功解析 JSON,因为响应并不总是返回所有属性(我不返回来自 REST 服务器的 null 字段)。
这就是我决定使用 Newtonsoft 的 Json.NET 的原因,因为它具有更强大的 Json 反序列化引擎。不幸的是,它不支持像 RestSharp 之类的模糊属性/字段名称(或者我没有找到任何名称),因此当我使用 JsonConvert.DeserializeObject<User>(response.Content) 之类的东西时,它也无法正确映射到我的 CLR 实体。
这是我的 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 e.g. */
public AccessToken AccessToken { get; set; }
public List<User> Friends { get; set; }
}
我想要的是一种将上述 JSON 解析为给定 CLR 对象的简单方法。我查看了 RestSharp 源代码并看到了JsonDeserializer 代码,并且我已经能够在JObject 上编写一个通用扩展方法DeserializeResponse<T>,它应该返回一个T 类型的对象。预期用途是这样的:
var user = JObject.Parse(response.Content).DeserializeResponse<User>();
上述方法应该将给定的 Json 响应解析为用户实体对象。这是我在 DeserializeResponse<User> 扩展方法中所做的实际代码 sn-p(它基于 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;
}
我猜转换应该是一件非常简单的事情,因为它是一项微不足道的任务。但是我已经搜索了很长一段时间,但仍然没有找到通过 Json.NET 实现它的方法(老实说,文档虽然有点理解并且缺少一些示例)。
任何帮助将不胜感激。
【问题讨论】:
-
这里有什么帮助吗?这是我第二次就 SO 提出任何问题但从未得到答案:/
-
@Guillaume 谢谢。我在发帖之前已经读过了。问题是我正在编写一个解析器,它应该能够处理它遇到的任何值,所以一个简单的
jToken.value<double>()将不起作用,因为我不知道它会是一个double。我不知道手头的类型。
标签: c# windows-phone-7 json.net restsharp