Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support serialization of Newtonsoft JSON.NET JObject #40

Open
eduardocampano opened this issue Sep 25, 2013 · 7 comments
Open

Support serialization of Newtonsoft JSON.NET JObject #40

eduardocampano opened this issue Sep 25, 2013 · 7 comments

Comments

@eduardocampano
Copy link

As the Newtonsoft JSON.NET JObject implements IEnumerable it is treated as an array for serialization instead of being serialized directly.

My issue came up in the following case: ASP.NET WebApi used JSON.NET to deserialize a complex JSON object during an API request. The deserialized type contains an IDictionary<string, object> property to allow custom info to be sent to the API. As part of the WebApi deserialization all the entries in the dictionary had JObject instance values. Trying to serialize the type instance again using SimpleJson the dictionary is not correctly serialized.

Thanks,
Eduardo

@prabirshrestha
Copy link
Member

can u post a sample code of class and json you are trying to serialize/deserialize.

@eduardocampano
Copy link
Author

I just pushed 2 failing unit tests to my fork
https://github.com/eduardocampano/simple-json/blob/f7f9238820b21663b7e38acb8fb66eb7b57c0e72/src/SimpleJson.Tests/SerializeObject.JsonNet.Tests.cs
I tried using TrySerializeNonPrimitiveObject in the IJsonSerializerStrategy but the code tries to serialize them as arrays because they implement IEnumerable.

@prabirshrestha
Copy link
Member

Why would you want to use both at the same time in the same code? The only place where you would want to use both at the same place would be server side using webapi and in client use simplejson.

@eduardocampano
Copy link
Author

In this case I'm building a logging library which serializes objects using SimpleJson. A consumer of this library is using WebApi with the default Json.Net serializer and sending the objects to log to my library. For now I provided him a SimpleJsonFormatter for WebApi and it solved the particular issue. But I would not like to force the library consumers to make this kind of changes. Maybe the solution is to have a hook where I can define a TypeConverter like Json.Net to force a type to use a specific converter before evaluating the default ones, as JObject is not able to reach the TrySerializeNonPrimitiveObject method.

@prabirshrestha
Copy link
Member

You might be interested in this discussion. https://twitter.com/PrabirShrestha/status/271392381226590209

Since JObject is IDictionary<string, JToken> we might need to check if it contains IDictionary<string, TAnything> then treat it as a json object. Or just try to cast it as IDictionary. Not sure if this works in all version of PCL.

@eduardocampano
Copy link
Author

Right, that could help, I will give that a try, thanks

@eduardocampano
Copy link
Author

Ok, I'm back on this after a while, casting as IDictionary doesn't work because IDictionary<,> does not implement it. I came up with this function

public bool IsIEnumerableKeyValuePairOfStringAndAnything(Type type)
{
    foreach (var interfaceType in type.GetInterfaces())
    {
        if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        {
            var genericArgument = interfaceType.GetGenericArguments()[0]; 
            if (genericArgument.IsGenericType && genericArgument.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)
                && genericArgument.GetGenericArguments()[0] == typeof(string))
            return true;
        }
    }

    return false;
}

It will check if the type to be serialized is an IEnumerable<KeyValuePair<string, TAnything>> so it can be treated as json object as you suggest. The current checks for IDictionary<string, object> and IDictionary<string, string> won't be necessary anymore. I haven't check its performance yet considering it will be executed a lot, results must be cached.

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants