序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()? [英] How to make JSON.Net serializer to call ToString() when serializing a particular type?

查看:31
本文介绍了序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Newtonsoft.Json 序列化程序将 C# 类转换为 JSON.对于某些类,我不需要序列化器到单个属性的实例,而是只在对象上调用 ToString,即

I am using Newtonsoft.Json serializer to convert C# classes to JSON. For some classes I don't need the serializer to an instance to individual properties, but instead just call ToString on the object, i.e.

public class Person
{
   public string FirstName { get; set; }
   public string LastName { get; set; }

   public override string ToString() { return string.Format("{0} {1}", FirstName, LastName ); }
}

我应该怎么做才能将 Person 对象序列化为 ToString() 方法的结果?我可能有很多这样的类,所以我不想最终得到一个特定于 Person 类的序列化程序,我想要一个可以适用于任何类的序列化程序(我猜是通过属性).

What should I do to get the Person object serialized as the result of its ToString() method? I may have many classes like this, so I don't want to end up with a serializer specific for Person class, I want to have one than can be applicable to any classe (via attribute I guess).

推荐答案

您可以使用自定义 JsonConverter:

You can do this easily with a custom JsonConverter:

public class ToStringJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }

    public override bool CanRead
    {
        get { return false; }
    }

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

要使用转换器,请使用 [JsonConverter] 属性装饰任何需要序列化为字符串的类,如下所示:

To use the converter, decorate any classes that need to be serialized as string with a [JsonConverter] attribute like this:

[JsonConverter(typeof(ToStringJsonConverter))]
public class Person
{
    ...
}

这是一个展示转换器的演示:

Here is a demo showing the converter in action:

class Program
{
    static void Main(string[] args)
    {
        Company company = new Company
        {
            CompanyName = "Initrode",
            Boss = new Person { FirstName = "Head", LastName = "Honcho" },
            Employees = new List<Person>
            {
                new Person { FirstName = "Joe", LastName = "Schmoe" },
                new Person { FirstName = "John", LastName = "Doe" }
            }
        };

        string json = JsonConvert.SerializeObject(company, Formatting.Indented);
        Console.WriteLine(json);
    }
}

public class Company
{
    public string CompanyName { get; set; }
    public Person Boss { get; set; }
    public List<Person> Employees { get; set; }
}

[JsonConverter(typeof(ToStringJsonConverter))]
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override string ToString() 
    { 
        return string.Format("{0} {1}", FirstName, LastName); 
    }
}

输出:

{
  "CompanyName": "Initrode",
  "Boss": "Head Honcho",
  "Employees": [
    "Joe Schmoe",
    "John Doe"
  ]
}

<小时>

如果您还需要能够从字符串转换回对象,您可以在转换器上实现 ReadJson 方法,以便它查找 public static Parse(string) 方法并调用它.注意:一定要把转换器的CanRead方法改成返回true(或者干脆删除CanRead重载),否则ReadJson 永远不会被调用.


If you also need to be able to convert from string back to an object, you can implement the ReadJson method on the converter such that it looks for a public static Parse(string) method and calls it. Note: be sure to change the converter's CanRead method to return true (or just delete the CanRead overload altogether), otherwise ReadJson will never be called.

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    MethodInfo parse = objectType.GetMethod("Parse", new Type[] { typeof(string) });
    if (parse != null && parse.IsStatic && parse.ReturnType == objectType)
    {
        return parse.Invoke(null, new object[] { (string)reader.Value });
    }

    throw new JsonException(string.Format(
        "The {0} type does not have a public static Parse(string) method that returns a {0}.", 
        objectType.Name));
}

当然,要使上述方法正常工作,您还需要确保在要转换的每个类上实现合适的 Parse 方法(如果它尚不存在).对于上面显示的示例 Person 类,该方法可能如下所示:

Of course, for the above to work, you will also need to make sure to implement a suitable Parse method on each class you're converting, if it doesn't already exist. For our example Person class shown above, that method might look something like this:

public static Person Parse(string s)
{
    if (string.IsNullOrWhiteSpace(s))
        throw new ArgumentException("s cannot be null or empty", "s");

    string[] parts = s.Split(new char[] { ' ' }, 2);
    Person p = new Person { FirstName = parts[0] };
    if (parts.Length > 1)
        p.LastName = parts[1];

    return p;
}

往返演示:https://dotnetfiddle.net/fd4EG4

这篇关于序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆