135

For some of my unit tests I want the ability to build up particular JSON values (record albums in this case) that can be used as input for the system under test.

I have the following code:

var jsonObject = new JObject();
jsonObject.Add("Date", DateTime.Now);
jsonObject.Add("Album", "Me Against The World");
jsonObject.Add("Year", 1995);
jsonObject.Add("Artist", "2Pac");

This works fine, but I have never really like the "magic string" syntax and would prefer something closer to the expando-property syntax in JavaScript like this:

jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against The World";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";
Karl Anderson
  • 34,606
  • 12
  • 65
  • 80

8 Answers8

194

Well, how about:

dynamic jsonObject = new JObject();
jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against the world";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";
Dimitar Dimitrov
  • 14,868
  • 8
  • 51
  • 79
  • 3
    Perfect! Exactly what I was looking for, completely forgot about `dynamic`. – Karl Anderson Aug 15 '13 at 16:16
  • I get 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'Date' error when I try to run your code. The way I could make it work is change the first line to: `dynamic jsonExpando = new ExpandoObject();` and add a line after your code: `JObject jsonObject = JObject.FromObject(jsonExpando);` – BornToCode Nov 27 '16 at 17:58
  • 3
    If you want to add a List<> to your Json object, you need to do something like `jsonObject.list = JToken.FromObject(mylist);`. – Steve Smith Jan 23 '18 at 12:04
  • You could use combination of index and property notation in case you hit field name having special character e.g. Create-Year". You will not b able to write jsonObject.Create-Year = 1995, but can use following. jsonObject["Create-Year"] = 1995; jsonObject.Artist = "2Pac"; – PAS Mar 21 '19 at 17:16
  • 3
    Now instead of magic strings you have magic properties :) – Yola Oct 15 '21 at 21:48
  • Will this escape characters like "? For example if I do json.Object.Name = "Test\"hehe", will the " be changed to \\" or will it break the syntax? – anaotha Nov 16 '21 at 13:45
  • If you into gamedev, don't forget that dynamic can't be used with IL2CPP – dylanh724 Jun 23 '22 at 04:39
  • BE REALLY CAREFUL ABOUT USING THIS It's going to fail when you need to run on il2cpp, such as if you're writing anything targetting iOS or Android. You should really only use the dynamic keyboard if you're certain that you're using Mono ONLY – pixelpax Nov 09 '22 at 20:06
97

You can use the JObject.Parse operation and simply supply single quote delimited JSON text.

JObject  o = JObject.Parse(@"{
  'CPU': 'Intel',
  'Drives': [
    'DVD read/writer',
    '500 gigabyte hard drive'
  ]
}");

This has the nice benefit of actually being JSON and so it reads as JSON.

Or you have test data that is dynamic you can use JObject.FromObject operation and supply a inline object.

JObject o = JObject.FromObject(new
{
    channel = new
    {
        title = "James Newton-King",
        link = "http://james.newtonking.com",
        description = "James Newton-King's blog.",
        item =
            from p in posts
            orderby p.Title
            select new
            {
                title = p.Title,
                description = p.Description,
                link = p.Link,
                category = p.Categories
            }
    }
});

Json.net documentation for serialization

Lee Jensen
  • 2,151
  • 2
  • 21
  • 23
72

Neither dynamic, nor JObject.FromObject solution works when you have JSON properties that are not valid C# variable names e.g. "@odata.etag". I prefer the indexer initializer syntax in my test cases:

JObject jsonObject = new JObject
{
    ["Date"] = DateTime.Now,
    ["Album"] = "Me Against The World",
    ["Year"] = 1995,
    ["Artist"] = "2Pac"
};

Having separate set of enclosing symbols for initializing JObject and for adding properties to it makes the index initializers more readable than classic object initializers, especially in case of compound JSON objects as below:

JObject jsonObject = new JObject
{
    ["Date"] = DateTime.Now,
    ["Album"] = "Me Against The World",
    ["Year"] = 1995,
    ["Artist"] = new JObject
    {
        ["Name"] = "2Pac",
        ["Age"] = 28
    }
};

With object initializer syntax, the above initialization would be:

JObject jsonObject = new JObject
{
    { "Date", DateTime.Now },
    { "Album", "Me Against The World" },
    { "Year", 1995 }, 
    { "Artist", new JObject
        {
            { "Name", "2Pac" },
            { "Age", 28 }
        }
    }
};
Jatin Sanghvi
  • 1,928
  • 1
  • 22
  • 33
  • 5
    The last one is definitively the best syntax to write json in c#. – Anthony Brenelière Feb 01 '18 at 16:00
  • see https://stackoverflow.com/questions/51015036/json-net-constructing-json-with-object-initializers/51017540#51017540 for how to do this with collections as well – kofifus Jun 25 '18 at 07:02
  • @AnthonyBrenelière I find the index initializer syntax a lot more clearer. For e.g. this `{ "Album", "Me Against The World" }` in the object initializer looks like a collection of items. – nawfal Oct 17 '22 at 17:40
37

There are some environment where you cannot use dynamic (e.g. Xamarin.iOS) or cases in where you just look for an alternative to the previous valid answers.

In these cases you can do:

using Newtonsoft.Json.Linq;

JObject jsonObject =
     new JObject(
             new JProperty("Date", DateTime.Now),
             new JProperty("Album", "Me Against The World"),
             new JProperty("Year", "James 2Pac-King's blog."),
             new JProperty("Artist", "2Pac")
         )

More documentation here: http://www.newtonsoft.com/json/help/html/CreatingLINQtoJSON.htm

Daniele D.
  • 2,624
  • 3
  • 36
  • 42
7

Sooner or later you will have property with a special character. e.g. Create-Date. The hyphen won't be allowed in property name. This will break your code. In such scenario, You can either use index or combination of index and property.

dynamic jsonObject = new JObject();
jsonObject["Create-Date"] = DateTime.Now; //<-Index use
jsonObject.Album = "Me Against the world"; //<- Property use
jsonObject["Create-Year"] = 1995; //<-Index use
jsonObject.Artist = "2Pac"; //<-Property use
PAS
  • 1,791
  • 16
  • 20
  • How does this answer the question? – Enigmativity Mar 21 '19 at 01:04
  • @Enigmativity, The point I am making is, you can use index notation and property notation together. i.e. obj[x] =x1; obj.y = y1 can be used in the same code. The combination of dynamic keyword and index notation answers the questions. No other answer has mentions this. Possibly, this should be comment than a answer. – PAS Mar 21 '19 at 17:14
  • I just think that the question is about not using magic strings, but this answer is giving him that. – Enigmativity Mar 21 '19 at 21:45
  • 1
    @Enigmativity, dynamic keyword just fools the compiler. So it's no different than arbitrary string. object of dynmaic type is not strongly typed. It's just a syntactic sugar. If the underlying object doesn't have property it will failed runtime. but you just cannot use properties if the name of property contains special characters e.g. 99BottlesOfBeer, namespace, It’s-All-Over. So in those cases, we can use indexed properties. Other answer make you think that it's one or other, but you can mix and match property and index. – PAS Mar 22 '19 at 01:39
4

Simple way of creating newtonsoft JObject from Properties.

This is a Sample User Properties

public class User
{
    public string Name;
    public string MobileNo;
    public string Address;
}

and i want this property in newtonsoft JObject is:

JObject obj = JObject.FromObject(new User()
{
    Name = "Manjunath",
    MobileNo = "9876543210",
    Address = "Mumbai, Maharashtra, India",
});

Output will be like this:

{"Name":"Manjunath","MobileNo":"9876543210","Address":"Mumbai, Maharashtra, India"}
Manjunath Bilwar
  • 2,215
  • 19
  • 16
0

You could use the nameof expression combined with a model for the structure you're trying to build.

Example:

record RecordAlbum(string Album, string Artist, int Year);

var jsonObject = new JObject
{
    { nameof(RecordAlbum.Album), "Me Against The World" },
    { nameof(RecordAlbum.Artist), "2Pac" },
    { nameof(RecordAlbum.Year), 1995 }
};

As an added benefit to removing the "magic string" aspect - this also will give you a little bit of refactor-ability. You can easily rename any given property name for the record and it should update the value returned by the nameof() expression.

BenJammin
  • 71
  • 5
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - [From Review](/review/late-answers/33870008) – Alberto Feb 22 '23 at 14:45
-4

You can use Newtonsoft library and use it as follows

using Newtonsoft.Json;



public class jb
{
     public DateTime Date { set; get; }
     public string Artist { set; get; }
     public int Year { set; get; }
     public string album { set; get; }

}
var jsonObject = new jb();

jsonObject.Date = DateTime.Now;
jsonObject.Album = "Me Against The World";
jsonObject.Year = 1995;
jsonObject.Artist = "2Pac";


System.Web.Script.Serialization.JavaScriptSerializer oSerializer =
         new System.Web.Script.Serialization.JavaScriptSerializer();

string sJSON = oSerializer.Serialize(jsonObject );
Nirmal
  • 924
  • 4
  • 9