【问题标题】:Is there a way to write custom JsonConverter per object有没有办法为每个对象编写自定义 JsonConverter
【发布时间】:2015-12-22 15:32:49
【问题描述】:

我有一个类似这样的 Json 对象:

{"company": "My Company",
"companyStart" : "2015/01/01",
"employee" : 
    { "name" : "john doe",
      "startDate" : 1420434000000 } }

我的 json 对象是这样的:

public class Company {
    public string company;
    public DateTime companyStart;
    public Employee employee;
}

public class Employee {
    public string name;
    public DateTime startDate;
 }

我的原始代码是这样反序列化的

JsonConvert.DeserializeObject<Company>(jsonString);

这段代码可以毫无问题地转换 Company.companyStart,但是当它到达 Employee.startDate 时,它​​不知道如何处理 Long。

This 帖子向我展示了如何创建自定义 JsonConverter 以将 long 转换为 DateTime,但正如您在我的例子中看到的那样,这会给我将 Company.companyStart 转换为 DateTime 的麻烦。

所以...我正在考虑做这样的事情:

public class Company : JsonBase {
    ...
}

public class Employee : JsonBase {
    ...
    Employee() { Converter = new CustomDateConverter(); }
}

public class JsonBase {
    private JsonConverter converter;
    [JsonIgnore]
    public JsonConverter Converter => converter ?? (converter = new StandardConverter());
}

JsonBase 将包含标准转换器或

在我的代码中,我会转换如下内容:

public T CreateJsonObject<T>() where T : JsonBase {
    JsonBase json = (T) Activator.CreateInstance(typeof (T));
    JsonConvert.DeserializeObject<T>(jsonString, json.Converter);
}

问题在于这不太有效,因为此方法将简单地使用最顶层的 Converter 来转换所有内容,而不是使用每个对象的转换器。

有没有办法为每个对象使用转换器?或者也许有更好的方法来做到这一点。

【问题讨论】:

  • 哎呀。我在帖子中遗漏了一些词:“JsonBase 将包含标准转换器或自定义转换器”
  • 到这里 -json2csharp.com 并粘贴您的 json,它将为您生成一个 C# 类。
  • 很酷的工具。但我需要将“startDate”作为 DateTime,而不是那么长。
  • 如果你使用Newtonsoft的JSON.NET你可以通过自定义来控制对象的序列化和反序列化:blog.maskalik.com/asp-net/…。您也可以使用内置的属性转换器/属性或编写自己的:newtonsoft.com/json/help/html/serializationattributes.htm

标签: c# json json.net


【解决方案1】:

如何调整您编写的自定义转换器以理解这两种格式:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.ValueType == typeof(string))
    {
        return DateTime.Parse((string)reader.Value);
    }
    else if (reader.ValueType == typeof(long))
    {
        return new DateTime(1970, 1, 1).AddMilliseconds((long)reader.Value);
    }
    throw new NotSupportedException();
}

或者,您可以通过使用 JsonConverter 属性来装饰模型的特定属性,从而仅将转换器应用于模型的特定属性:

public class Employee
{
    public string name;

    [JsonConverter(typeof(MyConverter))]
    public DateTime startDate;
}

这样您无需全局注册转换器,也不会与其他标准日期格式混淆。

【讨论】:

  • 与往常一样,我对我的解决方案进行了过度设计。您的 JsonConverter 属性非常简单。谢谢!
猜你喜欢
  • 2020-03-16
  • 2020-04-09
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-15
  • 1970-01-01
  • 2019-11-28
相关资源
最近更新 更多