簡體   English   中英

如何在序列化特定類型時使JSON.Net序列化程序調用ToString()?

[英]How to make JSON.Net serializer to call ToString() when serializing a particular type?

我使用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類的序列化器,我希望有一個可以適用於任何classe(通過屬性我猜)。

您可以使用自定義JsonConverter輕松完成此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

如果不打算大規模使用,有一種更快的方法可以做到這一點,在下面的示例中,它是為RecordType屬性完成的

[JsonIgnore]
public RecordType RecType { get; set; }

[JsonProperty(PropertyName = "RecordType")]
private string RecordTypeString => RecType.ToString();

您可以使用以下代碼簡單地嘗試使用Newtonsoft的JSON構建器庫並對類型為Person的對象進行Serilaize:

Dictionary<string, object> collection = new Dictionary<string, object>()
    {
      {"First", new Person(<add FirstName as constructor>)},
      {"Second", new Person(<add LastName as constructor>)},

    };
string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings
  {
    TypeNameHandling = TypeNameHandling.All,
    TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
  });

我沒有時間測試我的解決方案,但它應該工作。 假設您使用的所有類都是您自己的,為什么不在所有類上執行ToString覆蓋,並且需要使用Newtonsoft.Json序列化程序的類只能在ToString方法中序列化並返回。 這樣,當您想要獲取對象的序列化字符串時,您始終可以調用ToString。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM