Answering my own questions ... (I think I finally hugged Json Converters)
To answer my basic question about why one of the methods works and the other does not. I think the answer is that a method that does not work is simply incorrect. From what I can say, you need to use a writer object. If you do not, it will not work. (There may be scenarios where this is not the case, but I never found it.)
Json, [JsonIgnore]. ( ?)
- , . , , - . , , 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");
}
}
: ( , Entity Framework )
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();
, : ( , stringNameName )
{
"Id": 43,
"AccountName": "John",
"DefaultAssignToId": 43,
"OtherId": 19,
"OtherName": {
"BlahProp": "blah blah blah"
}
}
. : , -, Json, Role, .
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();
}
}
, , :
. , , , .
public class ShallowCopyCollectionConverter<TCollectionType, TCopyType> : JsonConverter
where TCollectionType : IEnumerable<TbdEntity>
where TCopyType : TbdEntity, new()
{
public override bool CanConvert(Type objectType)
{
return typeof(TCollectionType).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()) == false) return;
var entities = (TCollectionType)value;
writer.WriteStartArray();
foreach (var entity in entities)
{
serializer.Serialize(writer, entity.ShallowCopy<TCopyType>());
}
writer.WriteEndArray();
}
}
:
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"];
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();
}
}