Ability to allow Deserialization of object into array of objects

Apr 12, 2011 at 9:36 PM

I have run into an edge case and I would like input on my idea for handling it.  Here is the situation:  (I tried searching but didn't find anything)

I want to be able to take XML string data, convert it into JSON, then ultimately convert the Json into a .NET object.  

The XML is derived from a database with multiple parent->child->child relationships.

The edge case happens because of the following (from the documentation):  Multiple nodes with the same name at the same level are grouped together into an array.

Which means that if there is only one node it is treated as an object and NOT an array.   Therefore what happens in a large XML file we might have the child sometimes be an array (if it has more then one sibling) or an object (if it has no siblings).  This breaks when you try to deserialize into a .net object which is defining the property as an array.  The deserializer will work correctly when it hits the array and throw an exception when it hits the object.

What I would like the deserializer to do is to be able to handle this situation automatically.  If it has an object from the Json definition and a list from the .Net object, it would be able to ADD the object into the list if that list was of the correct type.  

This does break the JSON string data when you want to serialize from the .net object back into Json, but in my case this is not a problem as I am only going one way.  So if there was a way to allow this less strict deserialization rule it would be very handy to be able to do this.

I have already hacked out the code to be able to do this without too much effort but my questions are:

  1. Am I going about this the wrong way?  Is there a better solution or existing way in the library that I am not seeing.
  2. Has anyone else run into this edge case?
  3. If anyone finds this useful what is the best way to post the code?
  4. Should this have been posted on stackoverflow?



//we are inside the JsonSerializerInternaReader.CreateObject
            JsonObjectContract objectContract = contract as JsonObjectContract;
            if (objectContract != null)
                if (existingValue == null)
                    return CreateAndPopulateObject(reader, objectContract, id);

                return PopulateObject(existingValue, reader, objectContract, id);
//new code starts here
            JsonArrayContract arrayContract = contract as JsonArrayContract;
            if (arrayContract != null)
                if (existingValue == null)
                    return CreateAndPopulateArray(reader, arrayContract, id);

//hacked up method
 private object CreateAndPopulateArray(JsonReader reader, JsonArrayContract contract, string id)
            object newObject = null;
            object newArray = null;

            if (contract.DefaultCreator != null &&
              (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
                newArray = contract.DefaultCreator();

            JsonObjectContract objectContract = GetContractSafe(contract.CollectionItemType) as JsonObjectContract;
            newObject = objectContract.DefaultCreator();

            object result = CollectionUtils.CreateAndPopulateList(contract.CreatedType,
                (l, isTemporaryListReference) =>
                    l.Add(PopulateObject(newObject, reader, objectContract, id));

            return result;