2014-03-12 22 views
18

我正在使用Newtonsoft.Json序列化程序將C#類轉換爲JSON。對於一些課程我並不需要串行到一個實例的各個屬性,而只是調用toString的對象,即如何使JSON.Net序列化程序在序列化特定類型時調用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類的序列化程序,我想有一個可以適用於任何類(通過我猜的屬性)。

回答

32

您可以用自定義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

+1

非常感謝。正是我需要的。奇蹟般有效。 –

+0

很高興我能幫到你。 –

+0

@BrianRogers謝謝你的一個奇妙的答案。我想知道是否可以提供有關如何在轉換器中實現ReadJson()的任何見解,以便它將該字符串反序列化爲其兩個相應的屬性? – propagated

0

我沒有時間來測試我的解決方案,但它應該可以工作。假設你正在使用的所有類都是你自己的,爲什麼不在所有這些類上做一個ToString重寫,並且需要使用Newtonsoft.Json序列化器的類可以在ToString方法中被序列化並返回。這樣,當你想獲得對象的序列化字符串時,你總是可以調用ToString。

+4

首先,我不想混的ToString和序列化。他們有不同的目的。其次,我可以有複雜的對象圖,所以我應該依賴序列化程序遍歷圖並應用序列化算法。隨着你的appoach這將無法正常工作。 –

0

你可以簡單地嘗試Newtonsoft的JSON Builder庫和Serilaize使用這種代碼類型爲Person對象:

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

要使用:

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 
    }); 
+0

謝謝。我採用了Brian提出的方法(使用自定義轉換器)。 –

0

沒有這樣做,如果它不打算對所使用的快捷方式規模大,在下面的例子中,它是爲記錄類型屬性來完成

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

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