c# - 序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()?

标签 c# json serialization json.net tostring

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

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 类的序列化程序,我想要一个可以适用于任何类的序列化程序(我猜是通过属性)。

最佳答案

您可以使用自定义 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] 属性装饰任何需要序列化为字符串的类,如下所示:

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

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

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 永远不会被调用。

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 类,该方法可能如下所示:

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

关于c# - 序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22354867/

相关文章:

c# - 我应该如何在 C# 中从 C++ 转换 VAriant

mysql - 从laravel 4中的json数组获取元素

c# - 在 MVC 中绑定(bind)对象数组

java - 使用 Gson 从 JSON 字符串反序列化 iso-8601 格式的日期时出现问题

java - Jackson:如果有多个序列化器,使用哪一个?

c# - 我的页面不会显示我的多 View View

c# - Sitecore、GlassMapper、接口(interface)和动态代理

c# - 发送对变量的引用而不是它的值

c# - 序列化和反序列化时如何正确处理流处置和定位

c# - 使用 JSON.NET 序列化时隐藏 C# 属性