TL; DR版转换一个JToken(或字符串)给定类型
我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
应与date_joined
给出的值的DateTime对象。
全文
我在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" : "[email protected]",
"name" : "Uzair Sajid",
"twitter_screen_name" : "UzEE",
"join_date" : "2012-08-13T05:30:23Z05+00",
"timezone" : 5.5,
"access_token" : {
"token" : "nkjanIUI8983nkSj)*#)([email protected]",
"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>
扩展方法的实际代码片段(其基于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的任何问题,但从来没有得到答案:/ – 2012-08-13 09:27:13
http://stackoverflow.com/questions/9589218/get-value-from-jtoken-that-may-not-exist-最佳做法 – Guillaume 2012-08-13 12:06:51
@Guillaume谢谢。在发布之前,我已经阅读过。问题是我正在编写一个解析器,它应该能够处理它遇到的任何值,所以一个简单的'jToken.value()'将不起作用,因为我不知道它会是'double'。我不知道这种类型。 –
2012-08-13 19:32:06