Json.NET different property names resolving

Hi, boys and girls. Short post about how I resolved little local issue. Maybe someday someone might find this useful.

I’m developing library for 3rd party API for now. Format in which I’m receiving data is json. Trouble was with API answer’s formatting. API returns something like this:

{
    "server_time": "1459218903",
    "auth_user": {...},
    "some_entity_name": {some_entity_data}
}

where some_entity_name could be different for different API methods(“user”, “team” etc). But I wanted to map this field into single property within my generic:

    public class Answer<TEntity> where TEntity : class, IEntity
    {
        [JsonProperty("server_time")]
        public long ServerTime { get; set; }

        [JsonProperty("auth_user")]
        public Object AuthUser { get; set; }

        [JsonProperty("error")]
        public Error Error { get; set; }

        public TEntity Entity { get; set; } // <-- here
    }

Ofc JsonProperty attribute is useless for this case. So after some research I found pretty solution for that situation. I implemented custom ContractResolver and one attribute. So my class implementation for generic parameter becomes:

    [Attributes.JsonPropertyMap("user")]
    public class User : IEntity
    {

Attribute code(nothing special):

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class JsonPropertyMapAttribute : Attribute
    {
        public JsonPropertyMapAttribute(String mapToName)
        {
            MapToName = mapToName;
        }

        public String MapToName { get; set; }
    }

And that’s resolver code:

using ApiLibrary.ApiEntities.Attributes;
using Newtonsoft.Json.Serialization;
using System;
using System.Reflection;

namespace ApiLibrary.ApiEntities.Base
{
    public class EntityContractResolver<TEntity>: DefaultContractResolver where TEntity : class
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            if (propertyName == nameof(Answer.Entity))
            {
                Type entityType = typeof(TEntity);
                var jsonMapAttribute = entityType.GetTypeInfo().GetCustomAttribute<JsonPropertyMapAttribute>();
                if (!String.IsNullOrWhiteSpace(jsonMapAttribute?.MapToName))
                {
                    return jsonMapAttribute.MapToName;
                }
                else
                {
                    return entityType.Name.ToLowerInvariant();
                }
            }
            return base.ResolvePropertyName(propertyName);
        }
    }
}

Note: as I’m developing portable library(PCL) with C#6 you may notice little changed reflection call with entityType.GetTypeInfo()
Now for deserializing I call:

    JsonSerializerSettings settings = new JsonSerializerSettings()
    {
        ContractResolver = new ApiEntities.Base.EntityContractResolver<User>()
    };
    var deserialized = JsonConvert.DeserializeObject<ApiEntities.Base.Answer<User>>(jsonAnswer, settings);

That’s all. If you know how this could be implemented easier, then leave your thoughts in comments please.

Trip to json

json160

Not so far I figured for myself out, that json isn’t just an interchange data format. It grows with days and become more and more similar to XML. Before “Not so far” I have faced only with jsonp, which is used for XSS’es.

At this time I found out, that there is such stuff like:

  • JSONRequest – library with 4 functions(post, get, clear, cancel), which is used for safe XSS-requesting by excluding all headers and cookies, cause they usually contains sensitive data
  • JSON-RPC, which is similar to XML-RPC protocol
  • JSONPath – analogue of XPath but for json
  • JSON Schema – analogue of XSD

So for now is missed 1 important part from these JSON–XML stack – XSLT. Within 5 minutes in google I found 2 implementatios of such functionallity for json: JSONT(js) and JOML(java). I suppose we might see soon some more official and specified implementation for json transformation technology.