SenseNet / sn-client-dotnet

A .Net client for sensenet that makes it easy to use the REST API of the Content Repository.
https://www.sensenet.com/
GNU General Public License v2.0
7 stars 16 forks source link

SnClient Content is not serializable #114

Open kavics opened 1 year ago

kavics commented 1 year ago

Bug: The serialization to json string is not executed. The result is always an empty object (˙{}). Solution: Custom json converter is required. Proof of concept code (nested converter and ignored properties):

[JsonConverter(typeof(ContentConverter))]
public partial class Content : DynamicObject
{
    public class ContentConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(Content);
        }

        public override bool CanRead => false;
        public override bool CanWrite => true;

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotSupportedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var content = (Content)value;
            var json = new JObject();
            foreach (var field in content.FieldNames)
            {
                json[field] = JToken.FromObject(content[field], serializer);
            }

            var properties = content.GetType().GetProperties();
            foreach (var property in properties)
            {
                if(property.Name != "Item")
                    if(property.GetCustomAttribute<JsonIgnoreAttribute>() == null)
                        json[property.Name] = JToken.FromObject(property.GetValue(content), serializer);
            }

            foreach (var item in content._fields)
            {
                json[item.Key] = JToken.FromObject(item.Value, serializer);
            }

            json.WriteTo(writer);
        }
    }
...
    [JsonIgnore]
    public string ParentPath
    [JsonIgnore]
    public string[] FieldNames { get; private set; } = Array.Empty<string>();
    [JsonIgnore]
    private bool Existing { get; set; }
    [JsonIgnore]
    public ServerContext Server { get; internal set; }
    [JsonIgnore]
    public IRepository Repository { get; internal set; }

Discussion: This conversion can be slower than mapping to a well-known data transfer object with a mapper library (e.g. AutoMapper or Mapster)