首页 > 解决方案 > 如何使用 newtonsoft JSON 反序列化器反序列化 Geopoint?

问题描述

我正在使用以下类存储客户位置数据:

  public class CustomerData
{
    public string CustomerName { get; set; }
    public int CustomerNumber { get; set; }
    public string CustomerAddress { get; set; }
    public string CustomerCity { get; set; }
    public string CustomerZip { get; set; }
    public string CustomerState { get; set; }
    public Geopoint CustomerGeopoint { get; set; }

}

在 JSON 文件中......并使用如下服务检索数据:

public static async Task<ObservableCollection<CustomerData>> GetCustomerData()
    {
        var folder = ApplicationData.Current.LocalFolder;
        var dataFile = await folder.TryGetItemAsync("CustomerData.json") as IStorageFile;
        var stringResult = await FileIO.ReadTextAsync(dataFile);

        ObservableCollection<CustomerData> CustomersRetrievedData = JsonConvert.DeserializeObject<ObservableCollection<CustomerData>>(stringResult, new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.All
        });
        Customers = CustomersRetrievedData;
        return await Task.FromResult(CustomersRetrievedData);
    }

以及像这样保存数据:

       public static async void SaveCustomerData()
    {
        var folder = ApplicationData.Current.LocalFolder;
        StorageFile newFile = await folder.CreateFileAsync("CustomerData.json", CreationCollisionOption.ReplaceExisting);
        var stringData = JsonConvert.SerializeObject(Customers);
        await FileIO.WriteTextAsync(newFile, stringData);

    }

我的问题是,在所有地理点数据都在那里之后,当我尝试通过在 GetCustomerData() 方法中反序列化数据来读取数据时,出现以下错误:

找不到用于类型的构造函数Windows.Devices.Geolocation.Geopoint。一个类应该有一个默认构造函数、一个带参数的构造函数或一个标有 JsonConstructor 属性的构造函数

我不明白如何解决这个问题,我在 newtonsoft 文档上找不到任何东西,有人知道这是怎么做的吗?

标签: c#jsonuwp

解决方案


查看文档,Geopoint我们可以看到它有 3 个 .ctor,其中没有一个是无参数的。JSON.NET 需要一个无参数的 .ctor 来进行反序列化,正如您从收到的错误消息中看到的那样。

因此,您可以做的一件事是更改您的类以包含一个具有(您创建的)类型的属性,该类型反映了Geopoint结构(包括其所有属性),但还包括一个无参数的 .ctor。您甚至可以实现IGeoshape,以便它可以在任何IGeoshape需要的地方使用。

类似于以下内容:

public class GeopointProxy : IGeoshape {
    public GeopointProxy() { }

    private AltitudeReferenceSystem _altitudeReferenceSystem;
    // This is part of the IGeoshape interface, you can't change it's signature, and it's readonly.  Fun.
    [JsonIgnore]
    public AltitudeReferenceSystem AltitudeReferenceSystem { get { return _altitudeReferenceSystem; } }  

    public AltitudeReferenceSystem SettableAltitudeReferenceSystem {
        get {
            return AltitudeReferenceSystem;
        }
        set {
            _altitudeReferenceSystem = value;
        }
    }

    // rinse and repeat as appropriate for the other interface members and class properties

    // Then include a conversion function, or get fancy and add type conversion operators:
    public Geopoint ToGeopoint() {
        return new Geopoint(Position, AltitudeReferenceSystem, SpatialReferenceId);
    }
}

推荐阅读