C# 将 JToken(或字符串)转换为给定的类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11927135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting a JToken (or string) to a given Type
提问by Uzair Sajid
TL;DR Version
TL;DR 版本
I have a object of type JToken(but can also be a string) and I need to convert it into a Type contained in the typevariable:
我有一个类型的对象JToken(但也可以是 a 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);
The above resultshould be a DateTime object with the value given in date_joined.
以上result应该是一个 DateTime 对象,其值在date_joined.
Full Story
全文
I'm using both RestSharp and Json.NET in a Windows Phone project and I'm stuck while trying to deserialize JSON responses from a REST API.
我在 Windows Phone 项目中同时使用 RestSharp 和 Json.NET,但在尝试从 REST API 反序列化 JSON 响应时遇到了问题。
What I'm actually trying to accomplish is to write a generic method that can easily map my JSON response into my CLR entities, much like you can do with RestSharp already. The only problem is that the default RestSharp implementation isn't working for me and it fails to successfully parse the JSON since the response doesn't always return all the properties (I don't return fields which are nullfrom the REST server).
我实际上想要完成的是编写一个通用方法,该方法可以轻松地将我的 JSON 响应映射到我的 CLR 实体中,就像您可以使用 RestSharp 所做的那样。唯一的问题是默认的 RestSharp 实现对我不起作用,它无法成功解析 JSON,因为响应并不总是返回所有属性(我不返回null来自 REST 服务器的字段)。
That's why I decided to use Newtonsoft's Json.NET since it has a much more powerful Json deserializing engine. Unfortunately, it doesn't support fuzzy property/field names like RestSharp (or I haven't found any), so it also doesn't map correctly to my CLR entities when I use something like say JsonConvert.DeserializeObject<User>(response.Content).
这就是我决定使用 Newtonsoft 的 Json.NET 的原因,因为它具有更强大的 Json 反序列化引擎。不幸的是,它不支持像 RestSharp 这样的模糊属性/字段名称(或者我没有找到任何名称),因此当我使用诸如 say 之类的东西时,它也无法正确映射到我的 CLR 实体JsonConvert.DeserializeObject<User>(response.Content)。
Here's what my Json looks like (an example actually):
这是我的 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)*#)(kjb@K",
"scope" : [ "read", "write", "bake pies" ],
"expires" : 57723
},
"friends" : [{
"id" : 2347484",
"name" : "Bruce Wayne"
},
{
"id" : 996236,
"name" : "Clark Kent"
}]
}
And here's an example of my CLR entities:
这是我的 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; }
}
What I want is a simple way to parse the above JSON into the given CLR objects. I've looked around the RestSharp source code and have seen the JsonDeserializercode and I've been able to write a generic extension method DeserializeResponse<T>on JObjectthat should return a an object of type T. The intended use is something like this:
我想要的是一种将上述 JSON 解析为给定 CLR 对象的简单方法。我看了看周围的RestSharp源代码,并已经看到了JsonDeserializer代码,我已经能够编写一个通用的扩展方法DeserializeResponse<T>上JObject应该返回类型的对象T。预期用途是这样的:
var user = JObject.Parse(response.Content).DeserializeResponse<User>();
The above method should parse the given Json Response to a User entity object. Here's an actual code snippet of what I'm doing in the DeserializeResponse<User>extension method (its based on RestSharp code):
上面的方法应该将给定的 Json Response 解析为 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;
}
I'm guessing that the conversion should be a really straightforward thing to do since its a trivial task. But I've been searching for a quite a while now and still haven't found a way to do it via Json.NET (and lets be honest, the documentation is kinda though to understand and lacks some examples).
我猜转换应该是一件非常简单的事情,因为它是一项微不足道的任务。但是我已经搜索了很长一段时间,但仍然没有找到通过 Json.NET 实现的方法(老实说,文档虽然易于理解,但缺少一些示例)。
Any help would really be appreciated.
任何帮助将不胜感激。
采纳答案by Softlion
There is a ToObject method now.
现在有一个 ToObject 方法。
var obj = jsonObject["date_joined"];
var result = obj.ToObject<DateTime>();
It also works with any complex type, and obey to JsonPropertyAttribute rules
它也适用于任何复杂类型,并遵守 JsonPropertyAttribute 规则
var result = obj.ToObject<MyClass>();
public class MyClass
{
[JsonProperty("date_field")]
public DateTime MyDate {get;set;}
}
回答by L.B
System.Convert.ChangeType(jtoken.ToString(), targetType);
or
或者
JsonConvert.DeserializeObject(jtoken.ToString(), targetType);
--EDIT--
- 编辑 -
Uzair, Here is a complete example just to show you they work
Uzair,这是一个完整的示例,只是为了向您展示它们的工作原理
string 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)*#)(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);
回答by barjac
var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type);
throws a parsing exception due to missing quotes around the first argument (I think). I got it to work by adding the quotes:
由于缺少第一个参数周围的引号(我认为),会引发解析异常。我通过添加引号让它工作:
var i2 = JsonConvert.DeserializeObject("\"" + obj["id"].ToString() + "\"", type);
回答by Chirag
I was able to convert using below method for my WebAPI:
我能够使用以下方法为我的 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
}

