4

我正在使用 RestSharp 与远程服务器通信。我收到一个 JSON 序列化字符串,我可以将其反序列化为 ac# 对象。我还能够将 json 数组反序列化为 List。但是,我希望在 WPF 绑定中使用这些对象,因此为了方便起见,我需要将它们放在 ObservableCollection 中。但是,如果我尝试将属性从 List 更改为 ObservableCollection(或 IList、ICollection 或 Collection),我会在反序列化时遇到异常。

Unable to cast object of type 'RestSharp.JsonArray' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]

底层代码真的没有什么特别之处,但无论如何都在这里:

private ObservableCollection<StationDto> stations;

[JsonProperty(PropertyName = "stations")]
public ObservableCollection<StationDto> Stations
{
    get { return this.stations; }
    set
    {
        this.stations = value;
        RaisePropertyChanged(() => Stations);
    }
}

我知道接口不起作用,因为 Json.net 需要一个具体的类来序列化。

我已经做了相当多的谷歌搜索,但我还没有看到解决方案。是否有一种通常用于用于 json/rest 服务的手工代理的模式?

4

1 回答 1

7

查看 RestSharp的源代码,它似乎使用自己的内部 JSON 反序列化器(称为 SimpleJson),而不是使用 Json.Net。RestSharp 关于反序列化的文档确认反序列化器仅支持List<T>Dictionary<T1,T2>集合类型。 另一方面, Json.Net更加健壮,并且可以处理反序列化为 ObservableCollections。我用这篇文章末尾的代码试了一下,没有发现任何问题。考虑到这一点,我建议将 Json.Net 添加到您的解决方案中,并使用它来反序列化 REST API 调用的结果,而不是依赖 RestSharp 的内部反序列化器。有几种方法可以做到这一点:

  1. 您可以调用而不是 调用Execute<T>()。返回一个包含从请求返回的原始 JSON 字符串的属性。您可以获取此字符串并将其传递给 Json.Net 的方法。RestClientExecute()Execute()IRestResponseContentJsonConvert.DeserializeObject<T>()

  2. 创建一个实现 RestSharpIDeserializer接口的类。让这个类简单地交给 Json.Net 来完成反序列化 JSON 的实际工作。然后,您可以通过调用该类来告诉 RestSharp 使用此自定义反序列化器而不是它自己AddHandler()RestClient。根据文档,您以这种方式添加的处理程序将替换相同内容类型的现有处理程序。然后,您可以RestClient像现在一样继续使用ObservableCollections.

这是我用来测试 Json.Net 将反序列化为的代码ObservableCollection

class Program
{
    static void Main(string[] args)
    {
        string json = @"{""stations"":[{""Name"":""WXRT""},{""Name"":""WGN""}]}";

        Foo foo = JsonConvert.DeserializeObject<Foo>(json);

        foreach (StationDto dto in foo.Stations)
        {
            Console.WriteLine(dto.Name);
        }
    }
}

class StationDto
{
    public string Name { get; set; }
}

class Foo
{
    private ObservableCollection<StationDto> stations;

    [JsonProperty(PropertyName = "stations")]
    public ObservableCollection<StationDto> Stations
    {
        get { return this.stations; }
        set 
        { 
            this.stations = value;
            RaisePropertyChanged(() => Stations);
        }
    }

    private void RaisePropertyChanged(Func<ObservableCollection<StationDto>> coll)
    {
    }
}
于 2013-05-13T00:33:16.717 回答