facebook-csharp-sdk / simple-json

JSON library for .NET 2.0+/SL4+/WP7/WindowsStore with optional support for dynamic and DataContract
MIT License
380 stars 143 forks source link

Support naming strategies to map JSON to POCO and back #27

Closed haacked closed 11 years ago

haacked commented 11 years ago

The GitHub API uses Ruby casing for its JSON property names. For example:

{"user_name": "haacked", "id": 123}

But I'd like to still use proper .NET naming conventions on my POCO objects.

public class User {
    public int Id { get; set; }
    public string UserName { get; set; }
}

I looked at what it would take to implement an IJsonSerializerStrategy by simply inheriting from PocoJsonSerializerStrategy. The problem is there doesn't seem to be an easy hook to map JSON property names to CLR property names and back. I'd pretty much have to fully reimplement PocoJsonSerializerStrategy.

I'd like to propose a simple mapping for property to field names and back that by default would be an identity (it's always the same). But implementers could replace this mapping without having to rewrite all of PocoJsonSerializerStrategy.

prabirshrestha commented 11 years ago

The main reason for us to have IJsonSerializerStrategy was to support this. But never landed up implementing in a clean way.

Definitely need to implement some variant of CanAdd found in DataContractJsonSerializer. https://github.com/facebook-csharp-sdk/simple-json/blob/261f26937173bf263825e8500f5b6f2055514ccf/src/SimpleJson/SimpleJson.cs#L1479-L1489

Currently the only way is to use. #define SIMPLE_JSON_DATACONTRACT

[DataContract]
public class User {
    [DataMember(Name="id")]
    public int Id { get; set; }

    [DataMember(Name="user_name")]
    public string UserName { get; set; }
}

A virtual method in PocoJsonSerializerStrategy would be good. Or this could even go in IJsonSerializerStrategy..

Something like this.

public virtual string MapKey(string key, IDictionary<string, object> json,object obj, IDictionary<string, MemberInfo> members) {
    // return null if not found.
    return ToRubyCasing(key);
}

Can get some ideas from RestSharp too. https://github.com/restsharp/RestSharp/blob/master/RestSharp/Deserializers/JsonDeserializer.cs

haacked commented 11 years ago

The RestSharp approach looks good. I always try to advocate composition over inheritance as a solution. The mapping is a separate concern and could be fine as a class or a simple Func.

Do you think this is worthwhile and something you'll get to this soon? If not, I can work on it tonight or tomorrow. But I'd love for you to review my other PR first since I'd like to base this work off that code. :)

prabirshrestha commented 11 years ago

might need to use delegates as we need to support .net 2.0

RestSharp actually does use SimpleJson internally (https://github.com/restsharp/RestSharp/commit/f9623544c444ab5b4488756734a49a0a3e5ddcba) so should be able to port it easily.

due to my cast in the hand typing with one hand is very difficult. you could work on a PR for it :)