2

This code is part of a ASP.Net Web API controller, where I have a special requirement to modify certain values in the final Json, before sending it across to UI

My current code looks following:

// Web API controller

public partial class ViewRController
        {
       [HttpGet]
            public DataMapList FetchEmployeeDataList()
            {
                DataMapList returnDataMapList = new DataMapList();

                return (returnDataMapList);
            }
        }

// Type definition and details

    [JsonObject]
        [JsonConverter(typeof(DataMapListSerializer))]
        public class DataMapList
        {
            public List<Dictionary<object, object>> employeeSalaryMappingList = null;

            public DataMapList()
            {
                employeeSalaryMappingList = new List<Dictionary<object, object>>();
                employeeSalaryMappingList.Add(new Dictionary<object, object>());

                employeeSalaryMappingList[0].Add(1, 10000);
                employeeSalaryMappingList[0].Add(2, 13000);
                employeeSalaryMappingList[0].Add(3, 15000);

                employeeSalaryMappingList.Add(new Dictionary<object, object>());

                employeeSalaryMappingList[1].Add(4, 9000);
                employeeSalaryMappingList[1].Add(5, 12000);
                employeeSalaryMappingList[1].Add(6, 11000);
            }
        }

// Custom Json serializer

public class DataMapListSerializer : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var employeeSalaryDataMapList = value as DataMapList;
            var employeeSalaryMappingList = employeeSalaryDataMapList.employeeSalaryMappingList;


            writer.WriteStartObject();
            foreach (var employeeSalaryMappingDictionary in employeeSalaryMappingList)
            {
                writer.WritePropertyName("ED");
                writer.WriteStartObject();

                foreach (var keyValuePair in employeeSalaryMappingDictionary)
                {
                    writer.WritePropertyName("ID-" + keyValuePair.Key);
                    serializer.Serialize(writer, keyValuePair.Value);
                }

                writer.WriteEndObject();
            }

            writer.WriteEndObject();
        }       

        public override bool CanConvert(Type objectType)
        {
            return typeof(DataMapList).IsAssignableFrom(objectType);
        }
    }

Issue that I face is following is my result:

{ 
   "ED": { "ID-1": 10000, "ID-2": 13000, "ID-3": 15000 }, 
  "ED": { "ID-4": 9000, "ID-5": 12000, "ID-6": 11000 } 
}

However I expect the following result, since I am serializing a collection (.Net List type, .Net collection)

[ 
   "ED": { "ID-1": 10000, "ID-2": 13000, "ID-3": 15000 }, 
  "ED": { "ID-4": 9000, "ID-5": 12000, "ID-6": 11000 } 
]

In fact the current result when I try to validate in Json Lint, it shows valid Json but terminates a part of it,so it shows the following as valid Json, however that's just a diversion

{
    "ED": {
        "ID-4": 9000,
        "ID-5": 12000,
        "ID-6": 11000
    }
}

I have tried replacing writer.WriteStartObject(); and writer.WriteEndObject(); by writer.WriteStartArray(); and writer.WriteEndArray();, before the first foreach loop that traverse through the List in the type, but that leads to the exception, so doesnt help

"exceptionMessage": "Token StartArray in state ObjectStart would result in an invalid JSON object. Path '

any suggestion to resolve the issue let me know if you need any clarification

1 Answer 1

4

In JSON, name-value pairs must be within an object {}; they cannot be directly inside an array []. So this JSON that you are trying to create is not valid, and that is why you are getting an exception:

[ 
   "ED": { "ID-1": 10000, "ID-2": 13000, "ID-3": 15000 }, 
   "ED": { "ID-4": 9000, "ID-5": 12000, "ID-6": 11000 } 
]

In order to make it a valid collection, each of the ED name-value pairs must be wrapped in an object like this:

[ 
   { 
      "ED": { "ID-1": 10000, "ID-2": 13000, "ID-3": 15000 } 
   }, 
   { 
      "ED": { "ID-4": 9000, "ID-5": 12000, "ID-6": 11000 } 
   }
]

Once you see that, the solution becomes clear: in your DataMapListSerializer you need to use writer.WriteStartArray() and writer.WriteEndArray() outside your loop, and you need to add writer.WriteStartObject() and writer.WriteEndObject() inside your loop.

    writer.WriteStartArray();

    foreach (var employeeSalaryMappingDictionary in employeeSalaryMappingList)
    {
        writer.WriteStartObject();

            writer.WritePropertyName("ED");
            writer.WriteStartObject();

            foreach (var keyValuePair in employeeSalaryMappingDictionary)
            {
                writer.WritePropertyName("ID-" + keyValuePair.Key);
                serializer.Serialize(writer, keyValuePair.Value);
            }

            writer.WriteEndObject();

        writer.WriteEndObject();
    }

    writer.WriteEndArray();

Fiddle: https://dotnetfiddle.net/OT4HKM

Sign up to request clarification or add additional context in comments.

1 Comment

{ "data": [ { "ID44": 2, "ID43": "Block" }, { "ID44": 1, "ID43": "Train" } ] } This would be a valid Json, I have verified it. You are right, I need to wrap everything in the { } to make it a valid Json. So all that I need to do is wrap everything inside writer.WriteStartObject(); writer.WriteEndObject(); Modified the code at the link dotnetfiddle.net/OT4HKM thanks for providing the clarity

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.