有没有办法为每个对象编写自定义JsonConverter

时间:2015-12-22 15:32:50

标签: c# json json.net

我有一个像这样的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);
}

问题在于,这并不是很有效,因为这种方法只会使用最顶层的转换器来转换所有内容,而不是使用每个对象的转换器。

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

1 个答案:

答案 0 :(得分:7)

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

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;
}

这样您就不需要全局注册转换器,也不会弄乱其他标准日期格式。