回答我的問題...(我想我終於得到了我周圍的Json轉換頭)
要回答我的基本問題,爲什麼一個工作方式和其他沒有。我認爲答案只是這種行不通的方式是錯誤的。從我可以告訴,你需要使用作家對象。如果你不這樣做,它不會工作。 (可能有些情況並非如此,但我從未找到過。)
如果您只想從Json中刪除屬性,請使用[JsonIgnore]。 (簡單吧?)
如果你想改變一些值,你需要使用一個轉換器。通過使用Converter,您負責序列化Converter處理的任何對象。所以如果對象是一個像String這樣簡單的類型,或者是一個Int,那真的很簡單。如果它像數組或複雜對象那樣更復雜,那麼它需要更多的計劃。
這裏有一個簡單的字符串轉換的例子:
類連載:
public class Account
{
public int Id { get; set; }
public string AccountName { get; set; }
[JsonIgnore]
public virtual Account DefaultAssignTo { get; set; }
public int? DefaultAssignToId { get; set; }
[JsonIgnore]
public virtual ICollection<Role> Roles { get; set; }
[JsonIgnore]
public virtual Other Other { get; set; }
public int? OtherId { get; set; }
[JsonConverter(typeof(StringConverter))]
public string OtherName
{
get
{
return "Name = " + this.AccountName;
}
}
}
轉換器:
public class StringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(string).IsAssignableFrom(objectType);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (!this.CanConvert(value.GetType())) return;
writer.WriteValue("blah blah blah");
}
}
運行:(正如你可以看到我對我的數據使用實體框架)
using (var db = new Context())
{
var json = JsonConvert.SerializeObject(db.Accounts.FirstOrDefault(), Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Console.WriteLine(json);
}
返回:
{
"Id": 43,
"AccountName": "John",
"DefaultAssignToId": 43,
"OtherId": 19,
"OtherName": "blah blah blah"
}
一個是搞砸了我一個位的事情是,當使用writer.WriteStartObject()。基本上,如果你正在轉換一個複雜的對象,你需要使用它。如果你這樣做,那麼你需要創建所有的屬性名稱和值。在OP中,您可以看到我如何做到這一點的一個例子。最大的不利之處在於任何Json屬性的屬性裝飾都不會自動發生。所以如果可以的話,裝飾這個類並讓序列化器處理它。如果你錯誤地使用它,這是一個有趣的問題。
在字符串轉換器取代:
writer.WriteValue("blah blah blah");
有:
writer.WriteStartObject();
writer.WritePropertyName("BlahProp");
serializer.Serialize(writer, "blah blah blah");
writer.WriteEndObject();
來看,這又和這裏的輸出:(注意英文別名如何爲對象現在不是字符串)
{
"Id": 43,
"AccountName": "John",
"DefaultAssignToId": 43,
"OtherId": 19,
"OtherName": {
"BlahProp": "blah blah blah"
}
}
該角色集合還需要一個轉換器。首先需要注意兩點,您不需要指定屬性名稱,其次,Role類裝飾的任何Json屬性將按預期工作。
using BaseCollection = System.Collections.Generic.ICollection<JsonContractandConvert.Models.Role>;
public class RemoveAccountsFromRolesConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(BaseCollection).IsAssignableFrom(objectType);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (!this.CanConvert(value.GetType())) return;
var entities = value as BaseCollection;
if (entities == null) return;
writer.WriteStartArray();
foreach (var entity in entities)
{
entity.Accounts = null;
serializer.Serialize(writer, entity);
}
writer.WriteEndArray();
}
}
最後,這裏有一對夫婦我爲我的真正的項目創建轉換器:
這一個對象轉換爲淺拷貝。如果您有一個集合,其中包含該集合包含的集合可能導致自引用循環,那麼這非常有用。你爲什麼不使用簡單的`JsonIgnore`
public class DataSnapInConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DataSnapIn) == (objectType);
}
public override bool CanWrite
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (this.CanConvert(objectType) == false) return null;
var jo = JObject.Load(reader);
var typeName = jo["snapInType"] ?? jo["SnapInType"]; //the abstract classes have this property to identify what concrete class they are.
var typeNameString = typeName.ToString();
var deserializeType = Type.GetType(typeNameString);
if(deserializeType == null)
throw new Exception("SnapInType is null or does not reference a valid class.");
var result = Activator.CreateInstance(deserializeType);
serializer.Populate(jo.CreateReader(), result);
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
:
這人會用具體的類型轉換的抽象。 '{a = 1}'和'{a = 1,b = null}'有什麼區別?在讀者網站上,兩個json都將被轉換爲'b = null' –
JsonIgnore只有在你想忽略它時纔會起作用。在上面的例子中,如果我設置了entity.OtherString =「其他」;我犯了同樣的錯誤。 – Jeff
'我得到同樣的錯誤',什麼錯誤?這是一個簡單的序列化。 'JsonConvert.SerializeObject(obj)'就是這樣。在你的問題中不需要任何代碼(或任何轉換器)。 –