【问题标题】:dynamically change the json property name and serialize动态改变json属性名并序列化
【发布时间】:2017-06-08 10:52:42
【问题描述】:

我想动态更改 json 属性名并序列化对象。

这是我的两个不同实体的 json

为客户

{
  "userName": "66666",
  "password": "test1234",  
  "customersList": [
    {
      "address": "Test Stree2",
      "customerNumber": "US01-000281",
      "city": ""

    }
  ]
}

联系方式

{
  "userName": "66666",
  "password": "test1234",  
  "contactList": [
    {
      "address": "Test stree1",
      "contactNumber": "US01-000281",
      "city": ""

    }
  ]
}

持有这些数据的模型如下

public class URequest<T>
    {

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string userName { get; set; }

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string password { get; set; }    

       [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public IList<T> requestList { get; set; }

    }

在上面的代码requestList 中可能包含contactscustomer 的列表,但是在发送时我想将requestList json 属性名称更改为相应的实体名称,即对于customer,它将是customerList 和对于contact,序列化后为contactList

【问题讨论】:

  • 一个自定义解析器可以在这里为您提供帮助,stackoverflow.com/questions/37917164/…
  • 您的示例表明,除了标记标识符 (customer-/contactNumber) 之外,customercontact 实际上是相同的。您是否考虑过使用通用实体并仅添加类型标识符?它允许您添加更多类型(“lead”、“superuser”等),而无需更改所有编码。
  • 我也有其他类成员,只是为了简化示例,我在两个模型中都考虑了很少的类成员
  • 理论上你可以使用JsonConverter 类来做到这一点,虽然我更喜欢@Filburt 的建议:)
  • 是的,我们可以使用JsonConveter,但这就是问题所在:)

标签: c# json json.net


【解决方案1】:

您可以创建自定义 JsonConverter。

Using custom JsonConverter in order to alter the serialization of the portion of an object

例子

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

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

public class URequest<T>
{

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string userName { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string password { get; set; }

    [JsonIgnore]
    public IList<T> requestList { get; set; }

}

public class URequestConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(URequest<T>));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var objectType = value.GetType().GetGenericArguments()[0];
        URequest<T> typedValue = (URequest<T>) value;

        JObject containerObj = JObject.FromObject(value);

        containerObj.Add($"{objectType.Name.ToLower()}List", JToken.FromObject(typedValue.requestList));
        containerObj.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

你可以这样使用它

    [TestMethod]
    public void TestMethod1()
    {
        URequest<Customer> request = new URequest<Customer>();
        request.password = "test";
        request.userName = "user";
        request.requestList = new List<Customer>();

        request.requestList.Add(new Customer() { Name = "customer" });

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Formatting = Formatting.Indented;
        settings.Converters.Add(new URequestConverter<Customer>());

        Console.WriteLine(JsonConvert.SerializeObject(request, settings));
    }

【讨论】:

  • 我在GetGenericArguments()[0] 遇到错误,它说 type 不包含 `GetGenericArguments` 的定义,并且没有扩展方法接受“Type”类型的第一个参数`
  • 我已经使用 GetGenericTypeDefinition 而不是 GetGenericArguments 解决了一个错误,可以告诉我们如何处理复数词,例如而不是 Contact 我有“机会”,所以需要 @987654328 @
  • 问题是它增加了一个重复块{"userName":"666666","password":"ABC","companyId":"US01","page":1,"type":null,"IdProperty":"Contact","requestList":[{"birthdate":"2017-06-09","city":"","contactId":0}],"Id":0,"contactsList":[{"birthdate":"2017-06-09","city":"","contactId":0}],"contactId":0}
  • @Hunt, containerObj.Remove 删除重复块。
【解决方案2】:

使用ContentResolver我已经解决了问题

这里是代码

public class UserRequestResolver : DefaultContractResolver
{
    private string propertyName;

    public UserRequestResolver()
    {
    }
    public UserRequestResolver(string name)
    {
        propertyName = name;
    }
    public new static readonly UserRequestResolver Instance = new UserRequestResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyName == "requestList")
        {
            property.PropertyName = propertyName;              
        }
        return property;
     }
}

once 可以在构造函数中传递特定的属性名称。

JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ContractResolver = new UserRequestResolver("contactList");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多