7

I have this method in which I'm trying to create JSON string:

//my current file
using Newtonsoft.Json;
string key1 = "FirstKey";
string key2 = "SecondKey";
string key3 = "ThirdKey";
private string CreateJson(string val1,  string val2, string val3,string val4,  string val5, string val6)
{
    //process the six arguments and three key-related member variables to create a JSON array
    //don't want to use JsonConvert.SerializeObject the way I'm doing below as it requires creating a class

    var configs = new List<CustomClass>
                         { new CustomClass{ FirstKey = val1,SecondKey= val2,ThirdKey= val3}
                            , new CustomClass{ FirstKey= val4,SecondKey= val5,ThirdKey = val6}
                        };
    var jsonData = JsonConvert.SerializeObject(configs);
   return jsonData;
}

//A class in another file
public class CustomClass
{
    public string FirstKey { get; set; }
    public string SecondKey{ get; set; }
    public string ThirdKey{ get; set; }

}

I'm trying to create the JSON array using JSON.Net. The expected output is as below:

[{"FirstKey":val1,"SecondKey":val2,"ThirdKey":val3}
, {"FirstKey":val4,"SecondKey":val5,"ThirdKey":val6}]

Here val1 to val6 values should get replaced by the argument values at run-time.

Initially, since there were just three types of string key-value pairs, so I thought it would be pretty straightforward to create a JSON string simply by using string literals and appending then one after the other in JSON format. But soon I stumbled upon the world of escape characters which can deform a JSON string e.g. \r.

I had been using JSON.Net library in the past simply to serialize and deserialize objects using JSONConvert class and I never cared and was completely unaware about this handling of escape characters by JSON.Net library does behind the scene for us to keep the JSON string valid.

Anyways, coming back to my problem. I was able to solve my problem by creating a custom class having three properties FirstKey, SecondKey, and ThirdKey. Then, create an object of the class, then assign the values in arguments val1 and val2 to then and then use JsonConvert.SerializeObject API.

I want a very simply way of creating JSON string using JSON.Net NuGet package without involving custom classes. Creating a class CustomClass altogether feels like an overhead here. I'm looking for something of sort of like StringBuilder.Append API if it is available in the JSON library I'm using. I'm not sure if I'm missing any of the APIs in JSON.Net.

RBT
  • 24,161
  • 21
  • 159
  • 240
  • there are already answers, such as [so1](https://stackoverflow.com/questions/21021655/json-serialize-listkeyvaluepairstring-object), [so2](https://stackoverflow.com/questions/5124889/serialize-net-dictionarystring-string-into-json-key-value-pair-object) – Lei Yang Jul 04 '17 at 01:04
  • 1
    Select the values into an anonymous type, and serialize that. – stuartd Jul 04 '17 at 01:05
  • @stuartd since I need an JSON array as my final output so I'll have to create a `List`. How do I define `List` variable? – RBT Jul 04 '17 at 01:07
  • Possible duplicate of [How do I serialize a C# anonymous type to a JSON string?](https://stackoverflow.com/questions/331976/how-do-i-serialize-a-c-sharp-anonymous-type-to-a-json-string) – Michael Freidgeim Sep 21 '17 at 08:56

4 Answers4

16

As mentioned in the comments, you could just as easily have created it using anonymous objects.

private string CreateJson(string val1, string val2, string val3, string val4, string val5, string val6) {

    var configs = new[]
    { 
        new { FirstKey = val1, SecondKey = val2, ThirdKey = val3}, 
        new { FirstKey = val4, SecondKey = val5, ThirdKey = val6}
    };

    var jsonData = JsonConvert.SerializeObject(configs);

    return jsonData;
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • 3
    You can even use `JObject.FromObject` too! – code4life Jul 04 '17 at 01:31
  • @code4life although Nkosi's solution is pretty straightforward and what I was looking for but still I tried to accomplish it using `JObject.FromObject` also but I'm getting `System.ArgumentException` exception saying `Object serialized to Array. JObject instance expected.`. Can you please help me with some bare minimum code snippet to achieve the same using `JObject.FromObject` if it is possible? – RBT Jul 04 '17 at 02:08
  • 1
    I got it @code4life. Actually it was `JArray.FromObject` API. – RBT Jul 04 '17 at 02:44
  • I see this an Absolute win. – Sayed Muhammad Idrees Jun 26 '21 at 18:42
2

Here's an alternate way of doing it. My use case is I need to read a CSV file, and create JSON output based on the CSV headers. I do not know what the key names will be. Every CSV file could have different headers.

Rick Strahl shows us how to do it @ https://weblog.west-wind.com/posts/2012/aug/30/using-jsonnet-for-dynamic-json-parsing

And here's a simple implementation using JObject and JArray

Create a dotnet new console project and add the nuget package for Newtonsoft

dotnet new console -n "Json.TypeLess"
dotnet add package Newtonsoft.Json --version 13.0.1

Program.cs to have :

using Newtonsoft.Json.Linq;

namespace Json.TypeLess
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var records = new JArray();
            records.Add(CreateRecord("Johhny", "Singing"));
            records.Add(CreateRecord("Arjun", "Eating"));
            records.Add(CreateRecord("Sahil", "Reading"));
            records.Add(CreateRecord("Karthik", "Wuxia"));

            Console.WriteLine(records.ToString());
        }

        static JObject CreateRecord(string name, string likes)
        {
            var r = new JObject();
            r.Add("Name", name);
            r.Add("Likes", likes);
            return r;
        }
    }

}

Output

[
  {
    "Name": "Johhny",
    "Likes": "Singing"
  },
  {
    "Name": "Arjun",
    "Likes": "Eating"
  },
  {
    "Name": "Sahil",
    "Likes": "Reading"
  },
  {
    "Name": "Karthik",
    "Likes": "Wuxia"
  }
]

Without using NewtonSoft Json

The above can also be achieved using System.Text.Json.Nodes namespace from .net's native classes ( I tested using .net 6.0 )

Intead of JObject use JsonObject and instead of JArray use JsonArray and to get json output, use ToJsonString() method on the object

miniGweek
  • 380
  • 4
  • 15
1

Getting few clues from [@code4life][1]'s comment in accepted answer, I found out that it is achievable via JArray object as well found under Newtonsoft.Json.Linq namespace.

using Newtonsoft.Json.Linq;

private string CreateJson(string val1, string val2, string val3, string val4, string val5, string val6) 
{

    var configs = new[]
    { 
        new { FirstKey = val1, SecondKey = val2, ThirdKey = val3}, 
        new { FirstKey = val4, SecondKey = val5, ThirdKey = val6}
    };

    return JArray.FromObject(configs).ToString();
}

Note: Anonymous types which are being created through new { FirstKey = val1, SecondKey = val2, ThirdKey = val3} syntax can contain any .NET data type and not just strings which I've asked in my original post e.g.new { FirstKey = "AnyString", SecondKey = true, ThirdKey = DateTime.Now} [1]: https://stackoverflow.com/users/215741/code4life

RBT
  • 24,161
  • 21
  • 159
  • 240
0

There's JsonWriter, which is not much more than StringBuilder - you do not get much constraints and can possibly end up with incorrect document

Some time ago I wanted to create simple documents WITHOUT the overhead of serialization, but with the guarantee they will be correct.

The pattern I went with is:

var doc = JSONElement.JSONDocument.newDoc(true);

using (var root = doc.addObject())
{
    root.addString("firstName", "John");
    root.addString("lastName", "Smith");
    root.addBoolean("isAlive", true);
    root.addNumber("age", 27);
    using (var addres = root.addObject("address"))
    {
        addres.addString("streetAddress", "21 2nd Street");
        addres.addString("city", "New York");
        addres.addString("state", "NY");
        addres.addString("postalCode", "10021-3100");
    }
    using (var phoneNumbers = root.addArray("phoneNumbers"))
    {
        using (var phone = phoneNumbers.addObject())
        {
            phone.addString("type", "home");
            phone.addString("number", "212 555-1234");
        }
//[....]           
    }        
}
string output = doc.getOutput();

}

The module (< 300lines) is available here: https://github.com/AXImproveLtd/jsonDocCreate

d219
  • 2,707
  • 5
  • 31
  • 36