0

I want to use JSON.Net to serialize a complex C#.net object into JSON. The class structure is flexible (completely under my control), but JSON is needed in a specific format to communicate with another application. I require JSON in the following format, but need assistance composing the classes and nested collections:

{
 "Record_1": [  {  "key_1": "value_1", "key_N": "value_N"},   {  "key_1": "value_1", "key_N": "value_N"}],
 "Record_2": [  {  "key_1": "value_1" } ],
 "Record_N": [  {  "key_1": "value_1" } , { "key_N":"value_N"}],
 … Other properties (simple string key value pairs)
}
  • There will be 1 or more Record properties, the value of each Record is an array of objects.
  • The Record property names are not known (I have a list of possibilities, but do not want to hardcode them into the application).
  • There will be 1 or more objects in each array.
  • The objects in the array will have 1 or more string key value pairs. Again, property names are not known at compile time.

Since the Record properties were unknown, I tried using a dictionary of objects (Dictionary<string,object>) annotated with [JsonExtensionData]. The value object in the dictionary was another collection. However, that results in string properties with object values:

 "Record_1": { key_1: [ value_1, value_2, value_N] }, "Record_N": { key_1: [value_1]  }

Close, but not correct, the value of Record has to be an array.

Next, I tried using a list of lists of objects, but that didn't work either because the variable names of the lists are returned as the property names:

  "RecordSet": [
    {
      "Records": [
        {
          "Key_1": "Value_1"
        }
      ]
    },
    {
      "Records": [
        {
          "Key_1": "Value_1",
        }
      ]
    }
  ]

So this does result in an array objects, but contents of the object are not in the correct form.

I believe I need some combination of nested collections in my class to output the records in the required JSON format, but I don't know which. Hopefully someone else has encountered this situation before.

BTW: Currently, I'm directly writing to the JSON object to get the structure required. I'm hoping that there will be some performance increase in refactoring for serialization. I'm not looking to just add complexity so I can say I'm following object oriented coding principles. There will never be a need for deserialization of this JSON back into an object.

1
  • I'm pretty sure you are going to need to use either a Dictionary<string, string> or a dynamic to hold the things that look like { "key_1": "value_1", "key_N": "value_N"}. If you don't know what the property names are, you can't just use a plain old class Commented Jul 1, 2020 at 16:55

1 Answer 1

1

Updated answer (see comments for why):

The structure to match your JSON is Dictionary<string, List<Dictionary<string, string>>>. You'll have to figure out how to fill the property names you want for the first Dictionary key. One suggestion for that is to have an interface, something like ICanSerializeToSpecificJSONFormat, and then have all your classes implement that interface, with a method to convert the desired properties into this structure.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace SomeNamespace
{
    class Program
    {
        static void Main()
        {

            var d1 = new Dictionary<string, string>
            {
                { "key_1", "value_1" }
            };

            var d2 = new Dictionary<string, string>(d1)
            {
                { "key_2", "value_2" }
            };

            var objectToSerialize = new Dictionary<string, List<Dictionary<string, string>>>
            {
                { "Record_1", new List<Dictionary<string, string>> { d1, d2 } },
                { "Record_2", new List<Dictionary<string, string>> { d1 } }
            };

            string recordsAsJson = JsonConvert.SerializeObject(objectToSerialize);
            Console.WriteLine(recordsAsJson);
            // prints: 
            //  {"Record_1":[{"key_1":"value_1"},{"key_1":"value_1","key_2":"value_2"}],"Record_2":[{"key_1":"value_1"}]}
        }
    }
}

Original answer:

You were close. You tried Dictionary<> and List<List<>>, but you need List<Dictionary<>>. Here's a fully compiling example for you:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace SomeNamespace
{
    class RecordSet
    {
        public List<Dictionary<string, string>> Record_1 { get; set; }
        public List<Dictionary<string, string>> Record_2 { get; set; }
    }

    class Program
    {
        static void Main()
        {

            var d1 = new Dictionary<string, string>
            {
                { "key_1", "value_1" }
            };

            var d2 = new Dictionary<string, string>(d1)
            {
                { "key_2", "value_2" }
            };

            var records = new RecordSet
            {
                Record_1 = new List<Dictionary<string, string>> { d1, d2 },
                Record_2 = new List<Dictionary<string, string>> { d1 }
            };

            string recordsAsJson = JsonConvert.SerializeObject(records);
            Console.WriteLine(recordsAsJson);
            // prints: 
            //  {"Record_1":[{"key_1":"value_1"},{"key_1":"value_1","key_2":"value_2"}],"Record_2":[{"key_1":"value_1"}]}
        }
    }
}

Hopefully you can use this as a guide for creating your own RecordSet class (e.g. modifying to add the 'other properties' you mention).

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

1 Comment

This is great in giving me the JSON structure needed, but my requirement is that the properties be dynamic (properties as in JSON output). The difficulty is that the property names and number of properties are unknown. Hard-coding the property names in the RecordSet class won't work unless the JsonProperty annotation can be dynamic. The record names need to reflect the objects in the arrays, example: {"Dogs":[{"Name":"Spot"},{"Name":"Fido","Owner":"Jack"}],"Cars":[{"Make":"Ford","Plate":"VBC1000"},{"VIN":"xxx9999","Color":"Blue"}],"Computers":[{"OS":"Windows","Form Factor":"Laptop"}]}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.