【问题标题】:Generic class to store incoming json list using JsonConverter使用 JsonConverter 存储传入 json 列表的通用类
【发布时间】:2018-11-16 08:03:17
【问题描述】:

我正在尝试创建一个通用类,它可以存储任何类型的传入 json 的响应以避免拆箱我限制 T 必须从 RealmObject 派生

public class Response<T>  where T : RealmObject
{
    public string errorMessage { get; set; }
    public string status { get; set; }
    public string totalPages {get;set;}

    public IList<T> responseBody { get; set; }
}

这里,responseBody 参数能够存储从 web 服务获取的联系人列表、客户或订单数据。为了实现这一点,我试图 扩展 JsonConverter 以控制反序列化过程。

从服务器收到的Json如下(联系人类型数据)

{
  "errorMessage": "",
  "status": "Ok",
  "totalPages": 1,
  "contactsList": [
    {
      "firstName": "Ronald",
      "lastName": "Brownn"
    },
    {

      "firstName": "Elvis",
      "lastName": "Presley"
    }
  ]
}

以下是我的Contact 模特

[JsonCustomAttribute("contactsList")]

public class Contact : RealmObject
{

    public string firstName {get;set;}

    public string lastName { get; set; }        

}

到目前为止,我正在尝试使用 JsonConverter 反序列化传入的 json。在这里你可以看到我必须明确找到contactsList 属性,然后需要创建Response 具有泛型类型Contact 的对象以将所有Contact 数据添加到 responseBody。所以有什么办法可以使这些东西通用化,我的意思是动态找到contactListcustomerListorderList并动态创建Response&lt;Contact&gt;Response&lt;Customer&gt;等。

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    {

        JObject jObject = JObject.Load(reader);

        //For contact only
        JArray jArray = jObject.Property("contactsList").Value as JArray;
        Response<Contact> response = new Response<Contact>();
        response.responseBody = jArray.ToObject<IList<Contact>>();        

        serializer.Populate(jObject.CreateReader(), response);
        return response;


    }

【问题讨论】:

  • 正如我所提到的,这不仅仅是联系,将来还会有其他实体以及客户、订单等。我正在寻找通用解决方案
  • 好的,我想我明白你现在想要做什么了。通过使用Data 之类的通用属性名称来简化事情
  • 是的,我误解/误解了原始问题。
  • 您能控制从服务器返回的数据吗?
  • 不,我没有任何控制权

标签: c# xamarin json.net realm json-deserialization


【解决方案1】:

我最初尝试将其用作通用属性,但问题太多。

这是使用基于提供的类型的命名约定的转换器

public class ResponseConverter<T> : JsonConverter<Response<T>> where T : RealmObject {

    public override Response<T> ReadJson(JsonReader reader, Type objectType, Response<T> existingValue, bool hasExistingValue, JsonSerializer serializer) {
        JObject jObject = JObject.Load(reader);

        var typeName = typeof(T).Name;
        var propertyName = string.Format("{0}List", typeName);

        var response = new Response<T>();

        if (jObject.ContainsKey(propertyName) && jObject[propertyName].Type == JTokenType.Array) {
            response.responseBody = jObject.Property(propertyName).ToObject<IList<T>>();
        } else {
            response.responseBody = Enumerable.Empty<T>().ToList();
        }
        serializer.Populate(jObject.CreateReader(), response);
        return response;
    }

    public override void WriteJson(JsonWriter writer, Response<T> value, JsonSerializer serializer) {
        throw new NotImplementedException();
    }
}

手动使用会是这样的

var response = JsonConvert.DeserializeObject<Response<Contact>>(json, new ResponseConverter<Contact>());

对于不同类型的响应,您可以创建派生类并将转换器应用于该类

喜欢

[JsonConverter(typeof(ResponseConverter<Contact>))]
public class ContactResponse : Response<Contact> { }

[JsonConverter(typeof(ResponseConverter<Customer>))]
public class CustomerResponse : Response<Customer> { }

【讨论】:

  • 我有一个问题,我们如何使用这个 `public class ResponseConverter : JsonConverter> where T : RealmObject` 因为它抛出编译时错误the non-generic type 'JsonConverter' can not be used with type argument
  • 你在使用Newtonsoft.Json吗?
  • 是的。版本11.0.2
  • 我使用的是同一个版本,真的不知道为什么会出现编译时错误,因为Newtonsoft.Json.JsonConvertor 是一个没有涉及泛型类型的类
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 2014-04-19
  • 2016-08-09
  • 2018-01-14
相关资源
最近更新 更多