简体   繁体   中英

Is there a way to compose an anonymous type object from JSON without knowing about the object's structure before-hand?

I have a JSON string and I'd like to use to compose an object. I don't know about the object structure or properties yet, so I cannot code a structure using an anonymous type. I'm stuck in .NET 3.5 on this project, so I don't have access to the new .Net 4.0 features yet. My goal is to use the converted object in a template engine similar to WebForms, Spark, or Razor to populate template items in a document with values from a model.

I have tried JavaScriptSerializer, which has a DeserializeObject method, but it outputs a key/value dictionary instead of an object that resembles the JSON object. Any other ideas?

If it helps, here's a unit test that expresses what I'm trying to do:

    [TestClass]
    public class when_deserializing_json_to_an_object : given_a_json_serializer_context
    {
        private object _expectedSerializedObject;
        private string _jsonStringToDeserialize;
        private object _result;

        protected override void Context()
        {
            base.Context();

            _expectedSerializedObject = new
                                            {
                                                Test = "123"
                                            };

            _jsonStringToDeserialize = "{\"Test\":\"123\"}";
        }

        protected override void BecauseOf()
        {
            _result = ObjectConverter.Deserialize(_jsonStringToDeserialize);
        }

        [TestMethod]
        public void it_should_return_the_expected_object()
        {
            var modelType = _result.GetType();
            var modelProperties = modelType.GetProperties();
            var testProperty = modelProperties.SingleOrDefault(x => x.Name == "Test");

            testProperty.GetValue( _result, null ).ShouldEqual( "123" );            
        }
    }

public abstract class given_a_json_serializer_context : SpecificationBase
    {
        protected IObjectConverter ObjectConverter;
        private JavaScriptSerializer _javascriptSerializer;

        protected override void Context()
        {
            _javascriptSerializer = new JavaScriptSerializer();
            ObjectConverter = new JsonObjectConverter(_javascriptSerializer) as IObjectConverter;
        }
    }

(SpecificationBase is a class that our team uses to help us with BDD style specifications in MSTest)

So far, the production code born out of the specification above is as follows:

public class JsonObjectConverter : IObjectConverter
{
    private readonly JavaScriptSerializer _javascriptSerializer;

    public JsonObjectConverter(JavaScriptSerializer javascriptSerializer)
    {
        _javascriptSerializer = javascriptSerializer;
    }

    public object Deserialize(string json)
    {
        return _javascriptSerializer.DeserializeObject(json);
    }
}

At this point, it's clear that the JavaScriptSerializer isn't going to do the trick, because it just turns the JSON into a key/value pair dictionary.

You can't create an anonymous type like this but you can emit a new class.

Anonymous types are only anonymous to you. The compiler generates an actual type for all anonymous types and at run-time there is a real type associated with the anonymous types. Those types are not generated at run-time.

However, you can create a deserializer that uses Reflection.Emit or any similar (more powerful) library to generate a new class at run-time that has the appropriate structure and then instantiate and populate that class.

You might find this of help Json.NET:

"Json.NET is a popular high-performance JSON framework for .NET"

http://json.codeplex.com/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM