-1

To integrate with an API I need my C# to output the following json:

"fields": {  
    "name1": {  
        "key1": "value1",
        "key2": "value2"
    },
    "name2": {  
        "key3": "value3",
        "key4": "value4"
    },
    "etc..."
}

I don't understand how to set this up. Currently I'm using a class which I then serialize: JsonConvert.SerializeObject(document).

I have tried the following code:

public class Fields
{
    public string Name { get; internal set; }
         
    public Field myField { get; internal set; }

    public class Field
    {
        public string Value { get; internal set; }

        public string Key { get; internal set; }

        public Field(string value, string key)
        {
            Value = value;
            Key = key;
        }
    }

    public Fields(string name, Field myField)
    {
        Name = name;
        this.myField = myField;
    }
}
List<Fields> myFields = new List<Fields>();

foreach (var field in recipient.Fields)
    {
        myFields.Add(new Fields(field, new Fields.Field(name, value)));
    }

document.Fields = myFields;

But that results in:

"fields": [
    {
      "Name": "name1",
      "myField": {
        "key1": "value1",
        "key2": "value2"
      }
    },
    {
      "Name": "name2",
      "myField": {
        "key3": "value3",
        "key4": "value4"
      }
    }
]

The square brackets around the collection of fields need to be gone, and where it says "myField" it should be replaced by the variable "name1", "name2", etc.
Edit: I was mistaken, ignore the following part. It is possible for names to repeat themselves, the combination of the name and the second variable must be unique.
I could manually create the correct string with the given variables, but I feel like there has to be a better, "correct" way to achieve this.

Edit: fiddle

tbeest
  • 3
  • 2
  • 1
    You need to use a string-Field dictionary instead of a list – György Kőszeg Feb 23 '23 at 10:20
  • Welcome to StackOverflow! Could you please share with us the source object definition with some sample data? We could help you better if you share with us a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) – Peter Csala Feb 23 '23 at 11:38

2 Answers2

1

Json that you want is not valid if name1 can be equal to name2. So it is impossible to create the json you want. You can create it manually, using a StringBuilder for example, but you will not be able to deserialize it and get data (if you don't create your own json library with your own rules). The only structure that allows duplicates is a collection ( an array or a list for example). So discuss it with the users of API and update your post. We can offer dozens of different structures for you that are valid, but I can not see any sense in doing it. You can read any textbook instead.

IMHO the dictionaries are not the best structures for data models. It is always better to use fully typed objects instead of strings. You have to use dictionaries only if you can't use anything else.

Serge
  • 40,935
  • 4
  • 18
  • 45
  • I retried a few things and it seems you are indeed correct. With how it's set up elsewhere it seemed like duplicate names could be required, but it does not properly process them. Then it must be a limitation of the API I have been provided. Forgive the confusion. – tbeest Feb 23 '23 at 13:05
0

You can use Dictionary<string, Dictionary<string, string>> and create a model with this structure:

public class Fields
{
    public Dictionary<string, Dictionary<string, string>> Items { get; set; }
}

When a dictionary is serialized into JSON, the keys are used as property names and the values are used as property values. So to reproduce your JSON structure in your code, you need to initialize the model as follows:

var fields = new Fields();

var item1 = new Dictionary<string, string>()
{
    ["key1"] = "value1",
    ["key2"] = "value2"
};

var item2 = new Dictionary<string, string>()
{
    ["key3"] = "value3",
    ["key4"] = "value4"
};

fields.Items = new Dictionary<string, Dictionary<string, string>>()
{
    ["name1"] = item1,
    ["name2"] = item2,
};
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • Thank you to the answer! But I'm afraid that doesn't quite resolve it. I should've specified, but the names may not be unique. There might be a repeat, and as I understand that is not possible with a dictionary. – tbeest Feb 23 '23 at 10:34
  • I think repeating key values in json is a separate problem with a separate solution (and it seriously complicates deserialization, if you need it). But you can use dictionary with custom https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1 for it. – Vadim Martynov Feb 23 '23 at 10:38
  • @tbeest are you sure the API allows duplicate keys? It's [not recommended and some places even forbiddens it](https://stackoverflow.com/questions/21832701/does-json-syntax-allow-duplicate-keys-in-an-object) – Magnetron Feb 23 '23 at 11:39
  • @Magnetron thanks for the link. you are right and it can be an unexpected value in many systems and cause errors. that is why i wrote that such code will cause problems when deserializing the value. This would require writing a custom deserializer. But if necessary, you can implement a system where duplicate keys are allowed. – Vadim Martynov Feb 23 '23 at 11:45
  • 1
    I was mistaken about the duplication, forgive the confusion. – tbeest Feb 23 '23 at 13:08