4

I'm creating a database seeder for Cosmos DB (a document or JSON based DB). Some of the C# models have a property Config that is JSON so I've been using this type of code to set that property:

Config = JObject.FromObject(new { })

which works as does actually setting property(ies) inside the object:

Config = JObject.FromObject(new
{
  contextOptionSource = "$.domains.governmentEntityType_active"
}),

However, I can't figure out how to set Config to an array of objects. I tried actually using C# Models thinking that JObject would convert them for me like so:

Config = JObject.FromObject(
  new List<Question>
  {
    new Question
    {
      Key = "contact",
      Label = "Contact Person",
      HelpText = "",
      Config = JObject.FromObject(new {}),
      Type = "text",
      ContextTarget = "$.data.contact"
    },
    new Question
    {
      Key = "company",
      Label = "Company Name",
      HelpText = "",
      Config = JObject.FromObject(new {}),
      Type = "text",
      ContextTarget = "$.data.company"
    }
  }),

This compiled OK but when I run I get a runtime error "Object serialized to Array. JObject instance expected.'" Am I wrong to think that JObject should convert the C# models to JSON? If they have to be generic objects that's fine but I can't get the syntax right that the FromObject method will accept multiple objects inside this Config property.

Edit: Here's the JSON I'm trying to produce:

"config": {
  "questions": [{
    "key": "contact",
    "label": "Contact Person",
    "helpText": "Contact Person",
    "config": {},
    "type": QuestionKind.Textbox,
    "contextTarget": "$.data.contact",
    "enabledRule": null,
    "validationRules": [],
    "visibleRule": null
  },
  {
    "key": "company",
    "label": "Company Name",
    "helpText": "Company Name",
    "config": {},
    "type": QuestionKind.Textbox,
    "contextTarget": "$.data.company",
    "enabledRule": null,
    "validationRules": [],
    "visibleRule": null
  }]
}
renemadsen
  • 161
  • 1
  • 9
333Matt
  • 1,124
  • 2
  • 19
  • 29
  • 1
    `Config` must be of type `JToken` (or `JContainer`) not `JObject`. You can use [`JToken.FromObject()`](https://www.newtonsoft.com/json/help/html/Overload_Newtonsoft_Json_Linq_JToken_FromObject.htm) to generate it. See [JSON.NET: Why Use JToken--ever?](https://stackoverflow.com/q/38211719) and also [JContainer, JObject, JToken and Linq confusion](https://stackoverflow.com/a/38560188). – dbc May 21 '18 at 21:23
  • This would have been the answer if I had made the question clearer. See my explanation below. – 333Matt May 22 '18 at 12:59
  • Please edit your Q to include the clarification about expected result from your own answer. Also. see [mcve]. – Imre Pühvel May 23 '18 at 07:11

4 Answers4

7

Try JToken or JArray.

var Config = JToken.FromObject(
    new List<Question>
    {
        new Question
        {
            Key = "contact",
            Label = "Contact Person",
            HelpText = "",
            Config = JObject.FromObject(new {}),
            Type = "text",
            ContextTarget = "$.data.contact"
        },
        new Question
        {
            Key = "company",
            Label = "Company Name",
            HelpText = "",
            Config = JObject.FromObject(new {}),
            Type = "text",
            ContextTarget = "$.data.company"
        }
    }
    );

var result = Config.ToString();

The result is:

[
{
    "Label": "Contact Person",
    "HelpText": "",
    "Type": "text",
    "ContextTarget": "$.data.contact",
    "Config": {},
    "Key": "contact"
},
{
    "Label": "Company Name",
    "HelpText": "",
    "Type": "text",
    "ContextTarget": "$.data.company",
    "Config": {},
    "Key": "company"
}
]
Stringfellow
  • 2,788
  • 2
  • 21
  • 36
1

You need to know what type of JToken you want to create. For example, you can create a JObject either from a string value or from a .NET object. They are like factory methods. For example, if you want to create it from List<string>, you will have to tell the framework you will be creating a JArray from an in memory object:

var fromArray = JArray.FromObject(new List<string>
                {
                    "One",
                    "Two"
                });

Or that you will be creating JObject:

var fromObj = JObject.FromObject(new Customer() { Name = "Jon" });

Or you can create the tokens from JSON:

var fromJson = JArray.Parse("[\"One\", \"Two\"]");

Finally, you can just create JToken which is the parent of all the above classes (JArray, JObject) but then you will only have access to JToken properties and methods:

var Config = JToken.FromObject(
    new List<string>
    {
        "One",
        "Two"
    });

See this for the various tokens.

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
1

so the C# code I needed to do so was:

Config = JObject.FromObject(new
                                            {
                                                questions = JArray.FromObject(
                                                new List<Question>
                                                {
                                                    new Question
                                                    {
                                                        Key = "contact",
                                                        Label = "Contact Person",
                                                        HelpText = "",
                                                        Config = emptyJObject,
                                                        Type = "text",
                                                        ContextTarget = "$.data.contact"
                                                    },
                                                    new Question
                                                    {
                                                        Key = "company",
                                                        Label = "Company Name",
                                                        HelpText = "",
                                                        Config = emptyJObject,
                                                        Type = "text",
                                                        ContextTarget = "$.data.company"
                                                    }
                                                })
                                            })
333Matt
  • 1,124
  • 2
  • 19
  • 29
0

Use JArray, you can pick the constructor best suited for your needs here

FoxDeploy
  • 12,569
  • 2
  • 33
  • 48
freeAll
  • 82
  • 1
  • 4