【问题标题】:Json.NET (De)serialize MailAddressJson.NET(反)序列化邮件地址
【发布时间】:2017-08-03 21:27:52
【问题描述】:

在查看了许多 Google 搜索和 StackOverflow 帖子后,我得出结论,我可能需要创建自己的转换器。然而,这对我来说是非常非常新的,我不确定我在这些帖子中看到的哪些示例(如果有的话)我应该使用。

我有这个课(实际课比这个更复杂)

public class Person {
    [JsonProperty(PropertyName = "id")]
    public string PersonId { get; set; }

    [JsonProperty(PropertyName = "firstName")]
    public string PersonFirstName { get; set; }

    [JsonProperty(PropertyName = "email")]
    public MailAddress PersonEmail { get; set; }
}

我需要对下面的json进行序列化和反序列化

{
    "id" : "abc123"
    , "firstName" : "John"
    , "email" : "john@doe.com"
}

如何将 MailAddress 反序列化为包含 MailAddress.Addressstring,反之亦然。

我得到的错误是:

无法从 System.String 转换或转换为 System.Net.Mail.MailAddress

【问题讨论】:

  • 您遇到了什么问题? Json.NET 应该闭着眼睛做到这一点。
  • @CodingYoshi,你可以在这里看到dotnetfiddle.net/XbUVci 它不起作用。
  • @kiziu 谢谢。你太快了=)
  • 帮我们一个忙,并复制您遇到问题的例外情况。
  • 为什么这会得到 1) 在解释范围内的反对票,以及 2) 对 off-topic because... 的投票结束?

标签: c# json serialization json.net deserialization


【解决方案1】:

Json.NET 不适用于某些 .Net 类型,例如 System.Net.IPAddressSystem.Net.Mail.MailAddress。除非您愿意修改您的 JSON,否则您必须编写一个自定义转换器才能使用它们(代码取自 here):

public class MailAddressConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var mailAddress = value as MailAddress;
        writer.WriteValue(mailAddress == null? string.Empty : mailAddress.ToString());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var text = reader.Value as string;
        MailAddress mailAddress;

        return IsValidMailAddress(text, out mailAddress) ? mailAddress : null;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(MailAddress);
    }

    private static bool IsValidMailAddress(string text, out MailAddress value)
    {
        try
        {
            value = new MailAddress(text);
            return true;
        }
        catch
        {
            value = null;
            return false;
        }
    }
}

然后,您可以按照该帖子的作者的建议修改您的课程:

public class Person 
{
    [JsonProperty(PropertyName = "id")]
    public string PersonId { get; set; }

    [JsonProperty(PropertyName = "firstName")]
    public string PersonFirstName { get; set; }

    [JsonConverter(typeof(MailAddressConverter))]
    [JsonProperty(PropertyName = "email")]
    public MailAddress PersonEmail { get; set; }
}

..或者,你可以使用我的首选方式,也就是使用Json.NET的JsonSerializerSettings

public sealed class SerializerSettings : JsonSerializerSettings
{
    public SerializerSettings() : base()
    {
        this.Converters.Add(new MailAddressConverter());
    }
}

然后在你的Main():

JsonConvert.DefaultSettings = () => new SerializerSettings();

【讨论】:

  • 谢谢!也许我在谷歌搜索上很烂,即使这么多年过去了。你知道我在搜索 C# Newtonsoft.Json MailAddress 并且这篇文章没有出现,但是将它更改为 C# Json.Net MailAddress 并且它是第 4 行。这看起来不错。我试试看。
  • 我认为JsonConverter 的标准方法不是检查提供的值是否对给定类型有效,只需让构造函数/解析器对其进行排序并在失败时抛出异常。看这里-github.com/JamesNK/Newtonsoft.Json/blob/master/Src/…,它什么也抓不到,只是运行解析。
  • @RoLYroLLs 过去处理过这类问题(对于IPAddressIPEndpoint 对象),我立即认识到错误,只需要搜索C# newtonsoft MailAddress converter
【解决方案2】:

你的 json 结构需要是这样的,因为MailAddress 是一个对象:

{
    "id": "1",
    "firstName": "George",
    "email": {
        "DisplayName": "",
        "User": "test",
        "Host": "test.com",
        "Address": "test@test.com"
    }
}

您可以进行这样的快速测试以查看生成的 JSON:

var person = new Person
{
    PersonEmail = new System.Net.Mail.MailAddress("test@test.com"),
    PersonFirstName = "George",
    PersonId = "1"
};

var serialized = JsonConvert.SerializeObject(person);

【讨论】:

  • 谢谢,但我无法更改 Json,因为它是第 3 方数据。准确地说是使用 Salesforce API。
猜你喜欢
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多