将 JToken(或字符串)转换为给定的类型 [英] Converting a JToken (or string) to a given Type

查看:189
本文介绍了将 JToken(或字符串)转换为给定的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;DR 版本

我有一个 JToken 类型的对象(但也可以是 string),我需要将它转换为 type 中包含的 Type代码>变量:

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 type variable:

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 中给出.

The above result should be a DateTime object with the value given in date_joined.

全文

我在 Windows Phone 项目中同时使用 RestSharp 和 Json.NET,但在尝试反序列化来自 REST API 的 JSON 响应时遇到问题.

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.

我实际上想要完成的是编写一个通用方法,该方法可以轻松地将我的 JSON 响应映射到我的 CLR 实体中,就像您可以使用 RestSharp 所做的那样.唯一的问题是默认的 RestSharp 实现对我不起作用,它无法成功解析 JSON,因为响应并不总是返回所有属性(我不返回 null 来自 REST 服务器).

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 null from the REST server).

这就是我决定使用 Newtonsoft 的 Json.NET 的原因,因为它具有更强大的 Json 反序列化引擎.不幸的是,它不支持像 RestSharp 这样的模糊属性/字段名称(或者我没有找到任何名称),因此当我使用诸如 JsonConvert.DeserializeObject 之类的东西时,它也无法正确映射到我的 CLR 实体;(response.Content).

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).

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

Here's what my Json looks like (an example actually):

{
    "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 实体的示例:

And here's an example of my CLR entities:

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 类型的对象.预期用途是这样的:

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 JsonDeserializer code and I've been able to write a generic extension method DeserializeResponse<T> on JObject that should return a an object of type T. The intended use is something like this:

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

上述方法应该将给定的 Json Response 解析为 User 实体对象.这是我在 DeserializeResponse 扩展方法(基于 RestSharp 代码)中所做的实际代码片段:

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):

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 实现的方法(老实说,文档虽然有点理解但缺少一些示例).

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).

任何帮助将不胜感激.

推荐答案

现在有一个 ToObject 方法.

There is a ToObject method now.

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

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

It also works with any complex type, and obey to JsonPropertyAttribute rules

var result = obj.ToObject<MyClass>();

public class MyClass 
{ 
    [JsonProperty("date_field")]
    public DateTime MyDate {get;set;}
}

这篇关于将 JToken(或字符串)转换为给定的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆