How can I deserialize JSON with C#?
Asked Answered
B

19

561

I have the following code:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

The input in responsecontent is JSON, but it is not properly deserialized into an object. How should I properly deserialize it?

Bamberg answered 8/7, 2011 at 5:3 Comment(4)
Hey you may want to try this link techblog.procurios.nl/k/n618/news/view/14605/14863/…Aneroid
There's Json in System.Web.Helpers, there's JsonQueryStringConverter in System.ServiceModel.Web, there's JavascriptSerializer in System.Web.Script.Serialization, DataContractJsonSerializer in System.Runtime.Serialization.Json, heck MS has even decided to include third party Json.NET in its ASP.NET Web API. If you thought that wasn't enough, MS is coming up with System.Json but currently is unfit for consumption. Way to go Microsoft way to go.... I choose by the best looking namespace.Dramaturge
Just to complete, there is also JsonValue in Windows.Data.Json which is only for Windows 8 and above. I'm loving it. MS is on a mission :)Dramaturge
NewtonSoft has a comparison page on their site (might be biased but still interesting): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm. I especially liked the Nonsensical dictionary serialization row :)Cycad
M
436

I am assuming you are not using Json.NET (Newtonsoft.Json NuGet package). If this the case, then you should try it.

It has the following features:

  1. LINQ to JSON
  2. The JsonSerializer for quickly converting your .NET objects to JSON and back again
  3. Json.NET can optionally produce well formatted, indented JSON for debugging or display
  4. Attributes like JsonIgnore and JsonProperty can be added to a class to customize how a class is serialized
  5. Ability to convert JSON to and from XML
  6. Supports multiple platforms: .NET, Silverlight and the Compact Framework

Look at the example below. In this example, JsonConvert class is used to convert an object to and from JSON. It has two static methods for this purpose. They are SerializeObject(Object obj) and DeserializeObject<T>(String json):

using Newtonsoft.Json;

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
Mccay answered 8/7, 2011 at 5:5 Comment(10)
Can I deserialize to a var type variable, in the case I dont know the complete structure of my objective? Specifically, I'm consuming Rally User Stories, and I want to convert them to objects.Creight
@PedroDusso you can,here is the full docKnothole
@PeterWone: No, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expiry returns the string "2008-12-28T00:00:00", not a date. it can be turned into a Date via new Date(str), but JSON.parse knows nothing about dates. You'd have to pass in a reviver that checked each and every string value against a pattern.Restrictive
@T.J.Crowder - my bad. Just checked and not only are you right, but it's worse than that (He's dead, Jim!) with a subtle asymmetry incompatibility: JSON.stringify produces seconds to 2 decimal places "2015-09-28T01:08:03.704Z" which confounds Date.parse implicitly called by new Date(string). It's not hard to write a fixup and overload the built-in date parse, but lets all just use Moment.jsSmyrna
@PeterWone: It produces milliseconds, not seconds to two decimal places. (And for me, on FF, Chrome, and IE11, it's all three digits even if the last is 0.) That should be just fine, the milliseconds are in the format. This works for me on Chrome, Firefox, and IE11 for instance. For my part, I just use a replacer and a reviver. (Which is silly, it's well past time that JSON was upgraded to include such a fundamental concept as a date.)Restrictive
@T.J.Crowder my test of JSON.stringify(new Date()) produced "2015-09-28T01:08:03.704Z" on Microsoft Edge and new Date(JSON.stringify(new Date())) barfed,Smyrna
@PeterWone: "my test of JSON.stringify(new Date()) produced "2015-09-28T01:08:03.704Z" on Microsoft Edge" So that's with three digits of milliseconds "and new Date(JSON.stringify(new Date()))" That's really surprising, given that IE11 doesn't and Edge is in general better at standards. Does my fiddle above work on Edge? (Can't test Edge right now, too many VMs running as it is.)Restrictive
Since 3.703 seconds is the same as 3s and 703ms and the separator is a decimal point I put it to you that this is seconds to three decimal places.Smyrna
Note that if you need to use a property name that is actually a C# keyword like i.e "params", "int", "class", you could try naming the variables any other names you want then put [JsonProperty("params")], [JsonProperty("int")], JsonProperty("class")] on top of them.Dett
This was a good answer 9 years ago. But in 2022, Json.Net is no longer the only kid on the block. Also make sure you look at System.Tex.Json before committing to Json.NetAvian
M
368

As was answered here - Deserialize JSON into C# dynamic object?

It's pretty simple using Json.NET:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Or using Newtonsoft.Json.Linq :

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;
Moorman answered 24/7, 2013 at 18:58 Comment(4)
@MaxHodges, you are right. I just used inline "magic strings" for demonstrating how to parse JSON string values. Didn't want it to look complex with escaping double quotes. In real code we usually have JSON strings obtained from somewhere as variables or passed as parameters.Moorman
Without .net 4 you don't have 'dynamic' keyword. You can use 'var stuff' for declaration and instead of 'stuff.Name' and 'stuff.Address.City' you have 'stuff["Name"]' and 'stuff["Address"]["City"]' respectively.Pianette
@Pianette That gives you a value of type object, and you can't use indexing on a object.Oxy
@Oxy i'm pretty sure the Newtonsoft.Json variant returns a JObject. also, don't use Json.NET, even VS uses Newtonsoft.Json by now. can now even be used in VSIX without adding it to the packageIneradicable
S
157

Here are some options without using third party libraries:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

See the link for more information about System.Web.Helpers.Json.

Update: Nowadays the easiest way to get the Web.Helpers is to use the NuGet package.


If you don't care about earlier windows versions you can use the classes of the Windows.Data.Json namespace:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());
Stertorous answered 22/7, 2014 at 15:29 Comment(10)
Why I don't see System.Web.Helpers in my ASP.NET web site (4.5)? XElement, XPathSelectElement are not known for my VisualStudio. How to educate it?Stolen
Well, you have to add references for the corresponding libraries (as written in the comments above), see this article for more info. Also, this question might be of interest.Stertorous
I used the Web.Helpers method described here but ran into an issue that was solved by this post: #7067226Oxy
Located in #region Assembly System.ServiceModel.Web.dll, v3.5.0.0, + System.Runtime.Serialization.dll + System.XML.dllFields
it working with WPF.By using following namespace using System.Runtime.Serialization.Json; using System.Xml.XPath; using System.Xml.Linq;Airlia
You will need MVC to find System.Web.Helpers. It does not come with just standard Visual Studio 2015Winy
@ShahidNeermunda ... and using System.Xml; those using's need references to System.ServiceModel.Web, System.Runtime.SerializationUnquiet
Json.Net is hardly a third party component anymore. Microsoft use it themselves these days. It's the default serilizer on Web API.Avian
System.Web.Helpers.Json.Decode doesn't work for large JSON strings: I tried 115MB.Millburn
Web.Helpers is now suitable for .Net Core, just in case.Allin
H
66

If .NET 4 is available to you, check out: http://visitmix.com/writings/the-rise-of-json (archive.org)

Here is a snippet from that site:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

That last Console.WriteLine is pretty sweet...

Harberd answered 8/7, 2011 at 5:11 Comment(3)
Sorry, looks like things have changed since I initially answered. I'll have to take a look around and see which library is the correct one...Harberd
Looking forward to you finding this library. Edit : is it this one: dynamicjson.codeplex.com ?Enlargement
I dont know what class ElonU meant here, but there is "JsonValue" in Windows.Data.Json (which is only for Windows 8 and above - weird) and also the same "JsonValue" in System.Json which is still in preview and God alone knows if it will ever come out. MS confuses me when it comes to Json.Dramaturge
P
50

System.Text.Json

.NET core 3.0 comes with System.Text.Json built-in which means you can deserialize/serialize JSON without using a third-party library.

Serialize/Deserialize

To serialize your class(es) to JSON string:

var json = JsonSerializer.Serialize(model);

To deserialize the JSON into a strongly typed class:

var model = JsonSerializer.Deserialize<Model>(json);

Parse (.NET 6)

.NET 6 introduced the System.Text.Json.Nodes namespace which enables DOM parsing, navigation and manipulation in a similar manner to Newtonsoft.Json using the new classes JsonObject, JsonArray, JsonValue, and JsonNode.

// JsonObject parse DOM
var jsonObject = JsonNode.Parse(jsonString).AsObject();
// read data from DOM
string name = jsonObject["Name"].ToString();
DateTime date = (DateTime)jsonObject["Date"];
var people = jsonObject["People"].Deserialize<List<Person>>();

Similar methods apply to JsonArray. This answer provides more details on JsonObject.


One thing to note is that System.Text.Json does not automatically handle camelCase JSON properties when using your own code (however, it does when using MVC/WebAPI requests and the model binder).

To resolve this you need to pass JsonSerializerOptions as a parameter.

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json is also available for .Net Framework and .Net Standard as a Nu-get package System.Text.Json

Edit

In .NET 6 JsonNode.Parse() provides the functionality to parse "unknown" json

Panama answered 22/10, 2019 at 0:45 Comment(3)
What if you don't have a class? What if you only vaguely know what the json data is going to contain? Or if the keys exist at all?Scenic
@Scenic use JsonDocument.Parse.Panama
In .NET 6 JsonNode.Parse() provides the functionality to parse "unknown" jsonPanama
D
45

Another native solution to this, which doesn't require any 3rd party libraries but a reference to System.Web.Extensions is the JavaScriptSerializer. This is not a new but a very unknown built-in features there since 3.5.

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

and back

MyObject o = serializer.Deserialize<MyObject>(objectString)
Dietrich answered 20/12, 2014 at 22:58 Comment(3)
This is very nice, but it needs the web comonents, so unfortunately it doesn't work in .NET 4.0 Client Profile, which is the last .NET version for Windows XP. Full installation of .NET is possible, but many people stick just with Client Profile. In contrast, System.Runtime.Serialization.Json.DataContractJsonSerializer is suppoerted even in the Client Profile.Tribune
@fr34kyn01535: Windows XP has the second most marketshare on desktop. It's relevant.Mimesis
When I used JavaScriptSerializer to deseriarlize my object, it worked but it deserialized my date incorrectly. It should have been 4/19/2018 12:00AM but deserialized to 4/18/2018 08:00PM. NewtonSoft.Json.JsonConvert deserialized it as expected.Elixir
K
21

You could also have a look at the DataContractJsonSerializer

Kingsley answered 8/7, 2011 at 5:12 Comment(3)
this is better as it is compatible with .NET 3.5Pinard
it is also quite faster than JavaScriptSerializer,Pinprick
FYI, This is no longer supported in .Net Core.Avian
J
21

System.Json works now...

Install nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Sample:

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
Joey answered 8/8, 2018 at 5:27 Comment(2)
Trying to find an example of how to correctly use the modern System.Json has brought me here, after countless results for Json.NET/Newtonsoft.Json/"Newtson.Json" and older iterations of System.Json long since deprecated. Thank you for this.Sunil
for dotnet-core, from terminal do: "dotnet add package System.Json --version 4.5.0"Yorgo
E
14

Use this tool to generate a class based in your json:

http://json2csharp.com/

And then use the class to deserialize your json. Example:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': '[email protected]',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// [email protected]

References: https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+using+that+object https://www.newtonsoft.com/json/help/html/DeserializeObject.htm

Everest answered 10/1, 2019 at 4:29 Comment(0)
K
11

Try the following code:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}
Kletter answered 26/5, 2016 at 16:38 Comment(1)
Is this line doing anything...JavaScriptSerializer js = new JavaScriptSerializer(); Thanks in advance.Bratton
P
11

If JSON is dynamic as below

{
 "Items": [{
        "Name": "Apple",
        "Price": 12.3
    },
    {
        "Name": "Grape",
        "Price": 3.21
    }
   ],
   "Date": "21/11/2010"
}

Then, Once you install NewtonSoft.Json from NuGet and include it in your project, you can serialize it as

string jsonString = "{\"Items\": [{\"Name\": \"Apple\",\"Price\": 12.3},{\"Name\": \"Grape\",\"Price\": 3.21}],\"Date\": \"21/11/2010\"}";

        dynamic DynamicData = JsonConvert.DeserializeObject(jsonString);

        Console.WriteLine(   DynamicData.Date); // "21/11/2010"
        Console.WriteLine(DynamicData.Items.Count); // 2
        Console.WriteLine(DynamicData.Items[0].Name); // "Apple"

Source: How to read JSON data in C# (Example using Console app & ASP.NET MVC)?

Performing answered 14/7, 2020 at 8:59 Comment(0)
S
5

The following from the msdn site should I think help provide some native functionality for what you are looking for. Please note it is specified for Windows 8. One such example from the site is listed below.

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

It utilizes the Windows.Data.JSON namespace.

Stegodon answered 24/2, 2015 at 12:18 Comment(3)
Nice, but "Minimum supported client: Windows 8"Oxbridge
i think its no more supported and now there is newtonsoft json dll icouldnt find windows.data.jsonBandwidth
@virtouso, as watbywbarif pointed out it's actually rather new, however minimal support from Microsoft, only works within Windows 8.Stegodon
I
0

You can use following extentions

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}
Inestimable answered 24/5, 2020 at 1:12 Comment(0)
M
0

I ended up with a simple class that creates types on the fly, instantiate them and hydrate them, mirroring the structure of the input JSON.

enter image description here

You can find it here:

https://github.com/starnutoditopo/JsonToObject

JsonToObjectConverter.cs

using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.Json;

namespace JsonToObject;

/// <summary>Provides functionalities to convert JSON strings in to CLR objects.</summary>
public class JsonToObjectConverter
{
    private class Counter
    {
        private ulong count;
        public Counter()
        {
            this.count = 0;
        }

        public ulong Next()
        {
            this.count++;
            return this.count;
        }
    }


    private static ulong assemblyGenerationCounter;
    private readonly JsonToObjectConverterOptions options;

    static JsonToObjectConverter()
    {
        assemblyGenerationCounter = 0;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using default options.
    /// </summary>
    /// <param name="options">The options.</param>
    public JsonToObjectConverter()
        : this(new JsonToObjectConverterOptions())
    {
    }


    /// <summary>
    /// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using the specified options.
    /// </summary>
    /// <param name="options">The options.</param>
    public JsonToObjectConverter(JsonToObjectConverterOptions options)
    {
        this.options = options;
    }

    /// <summary>Converts a JSON string to an instance of a CLR object.</summary>
    /// <param name="jsonString">The json string.</param>
    /// <returns>
    ///   <br />
    /// </returns>
    public object? ConvertToObject(string jsonString)
    {
        JsonSerializerOptions opt = new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        };
        JsonElement rawResult = JsonSerializer.Deserialize<JsonElement>(jsonString, opt);
        object? result = ToStronglyTypedObject(rawResult);
        return result;
    }

    private object? ToStronglyTypedObject(JsonElement? nullableJsonElement)
    {
        string assemblyNameString;
        ulong assemblyId = Interlocked.Increment(ref assemblyGenerationCounter);
        try
        {
            assemblyNameString = string.Format(this.options.RuntimeGeneratedAssemblyNameTemplate, assemblyId.ToString(CultureInfo.InvariantCulture));
        }
        catch
        {
            throw new InvalidOperationException($@"Unable to generate assembly name using template '{this.options.RuntimeGeneratedAssemblyNameTemplate}' and id '{assemblyId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedAssemblyNameTemplate)} property in the options.");
        }
        ModuleBuilder moduleBuilder = CreateModuleBuilder(assemblyNameString, this.options.RuntimeGeneratedModuleName);
        Counter typeGenerationCounter = new Counter();
        var result = ToStronglyTypedObject(nullableJsonElement, moduleBuilder, typeGenerationCounter);
        return result;
    }
    private object? ToStronglyTypedObject(
        JsonElement? nullableJsonElement,
        ModuleBuilder moduleBuilder,
        Counter typeGenerationCounter
    )
    {
        if (nullableJsonElement == null)
        {
            return null;
        }

        JsonElement jsonElement = nullableJsonElement.Value;

        switch (jsonElement.ValueKind)
        {
            case JsonValueKind.Undefined:
                return null;
            case JsonValueKind.String:
                return jsonElement.GetString();
            case JsonValueKind.False:
                return false;
            case JsonValueKind.True:
                return true;
            case JsonValueKind.Null:
                return null;
            case JsonValueKind.Number:
                {
                    if (jsonElement.TryGetDouble(out var result))
                    {
                        return result;
                    }
                }
                throw new InvalidOperationException($"Unable to parse {jsonElement} as number.");
            case JsonValueKind.Object:
                {
                    ulong typeId = typeGenerationCounter.Next();
                    string typeName;
                    try
                    {
                        typeName = string.Format(this.options.RuntimeGeneratedTypeNameTemplate, typeId.ToString(CultureInfo.InvariantCulture));
                    }
                    catch
                    {
                        throw new InvalidOperationException($@"Unable to generate type name using template '{this.options.RuntimeGeneratedTypeNameTemplate}' and id '{typeId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedTypeNameTemplate)} property in the options.");
                    }

                    TypeBuilder typeBuilder = CreateTypeBuilder(moduleBuilder, typeName);
                    Dictionary<string, object?> propertyValues = new Dictionary<string, object?>();
                    foreach (var property in jsonElement.EnumerateObject())
                    {
                        string propertyName = property.Name;
                        object? propertyValue = ToStronglyTypedObject(property.Value, moduleBuilder, typeGenerationCounter);
                        Type propertyValueType;
                        if (null == propertyValue)
                        {
                            propertyValueType = typeof(object);
                        }
                        else
                        {
                            propertyValueType = propertyValue.GetType();
                        }
                        CreateAutoImplementedProperty(typeBuilder, propertyName, propertyValueType);
                        propertyValues.Add(propertyName, propertyValue);
                    }

                    Type resultType = typeBuilder.CreateType()!;
                    object result = Activator.CreateInstance(resultType)!;
                    foreach (var pair in propertyValues)
                    {
                        var propertyInfo = resultType.GetProperty(pair.Key)!;
                        propertyInfo.SetValue(result, pair.Value);
                    }
                    return result;
                }
            case JsonValueKind.Array:
                {
                    List<object?> list = new List<object?>();
                    foreach (var item in jsonElement.EnumerateArray())
                    {
                        object? value = ToStronglyTypedObject(item, moduleBuilder, typeGenerationCounter);
                        list.Add(value);
                    }
                    return list.ToArray();
                }
            default:
                throw new InvalidOperationException($"Value type '{jsonElement.ValueKind}' is not supported");
        }
    }

    private static ModuleBuilder CreateModuleBuilder(
            string assemblyNameString,
            string moduleName
        )
    {
        // create assembly name
        var assemblyName = new AssemblyName(assemblyNameString);
        // create the assembly builder
        AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

        // create the module builder
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
        return moduleBuilder;
    }

    private static TypeBuilder CreateTypeBuilder(
            ModuleBuilder moduleBuilder,
            string typeName
        )
    {
        // create the type builder
        TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
        typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
        return typeBuilder;
    }

    private static void CreateAutoImplementedProperty(
        TypeBuilder builder,
        string propertyName,
        Type propertyType
        )
    {
        const string PrivateFieldPrefix = "m_";
        const string GetterPrefix = "get_";
        const string SetterPrefix = "set_";

        // Generate the field.
        FieldBuilder fieldBuilder = builder.DefineField(
            string.Concat(PrivateFieldPrefix, propertyName),
                          propertyType, FieldAttributes.Private);

        // Generate the property
        PropertyBuilder propertyBuilder = builder.DefineProperty(
            propertyName, PropertyAttributes.HasDefault, propertyType, null);

        // Property getter and setter attributes.
        MethodAttributes propertyMethodAttributes =
            MethodAttributes.Public | MethodAttributes.SpecialName |
            MethodAttributes.HideBySig;

        // Define the getter method.
        MethodBuilder getterMethod = builder.DefineMethod(
            string.Concat(GetterPrefix, propertyName),
            propertyMethodAttributes, propertyType, Type.EmptyTypes);

        // Emit the IL code.
        // ldarg.0
        // ldfld,_field
        // ret
        ILGenerator getterILCode = getterMethod.GetILGenerator();
        getterILCode.Emit(OpCodes.Ldarg_0);
        getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
        getterILCode.Emit(OpCodes.Ret);

        // Define the setter method.
        MethodBuilder setterMethod = builder.DefineMethod(
            string.Concat(SetterPrefix, propertyName),
            propertyMethodAttributes, null, new Type[] { propertyType });

        // Emit the IL code.
        // ldarg.0
        // ldarg.1
        // stfld,_field
        // ret
        ILGenerator setterILCode = setterMethod.GetILGenerator();
        setterILCode.Emit(OpCodes.Ldarg_0);
        setterILCode.Emit(OpCodes.Ldarg_1);
        setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
        setterILCode.Emit(OpCodes.Ret);

        propertyBuilder.SetGetMethod(getterMethod);
        propertyBuilder.SetSetMethod(setterMethod);
    }
}

JsonToObjectConverterOptions.cs

namespace JsonToObject;

/// <summary>
/// Defines the options to instantiate a <see cref="JsonToObjectConverter" /> object.
/// </summary>
public class JsonToObjectConverterOptions
{
    private const string CONSTANTS_RuntimeGeneratedModuleName = $"RuntimeGeneratedModule";
    private const string CONSTANTS_RuntimeGeneratedAssemblyNameTemplate = "RuntimeGeneratedAssembly_{0}";
    private const string CONSTANTS_RuntimeGeneratedTypeNameTemplate = "RuntimeGeneratedType_{0}";

    /// <summary>Gets or sets the name of the runtime-generated module.</summary>
    /// <value>The name of the runtime-generated module.</value>
    public string RuntimeGeneratedModuleName { get; set; } = CONSTANTS_RuntimeGeneratedModuleName;

    /// <summary>Gets or sets the template to use to generate the name of runtime-generated assemblies.</summary>
    /// <value>The template to use to generate the name of runtime-generated assemblies.</value>
    /// <remarks>Should contain a "{0}" placeholder.</remarks>
    public string RuntimeGeneratedAssemblyNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedAssemblyNameTemplate;

    /// <summary>Gets or sets the template to use to generate the name of runtime-generated types.</summary>
    /// <value>The template to use to generate the name of runtime-generated types.</value>
    /// <remarks>Should contain a "{0}" placeholder.</remarks>
    public string RuntimeGeneratedTypeNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedTypeNameTemplate;
}
Mandate answered 25/5, 2022 at 14:53 Comment(0)
P
0

Here's a complete, runnable example using csc v2.0.0.61501.

Packages:

nuget install Microsoft.AspNet.WebApi.Core
nuget install Microsoft.Net.Http
nuget install Newtonsoft.Json

Code:

using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;

public static class App
{
    static void Main()
    {
        MainAsync().GetAwaiter().GetResult();
    }

    static async Task MainAsync()
    {
        string url = "https://httpbin.org/get";
        var client = new HttpClient();

        // The verbose way:
        //HttpResponseMessage response = await client.GetAsync(url);
        //response.EnsureSuccessStatusCode();
        //string responseBody = await response.Content.ReadAsStringAsync();

        // Or:
        string responseBody = await client.GetStringAsync(url);

        var obj = JsonConvert.DeserializeObject<dynamic>(responseBody);
        Console.WriteLine(obj);
        Console.WriteLine(obj.headers.Host);
    }
}

Compiler command:

 csc http_request2.cs -r:".\Microsoft.AspNet.WebApi.Core.5.2.9\lib\net45\System.Web.Http.dll" -r:".\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll" -r:".\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll"

Output:

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-633dce52-64f923bb42c99bf46f78672c"
  },
  "origin": "98.51.7.199",
  "url": "https://httpbin.org/get"
}
httpbin.org

Per Could not load file or assembly Newtonsoft.json. The system cannot find the file specified, I had to move the Newtonsoft.Json.dll next to the compiled binary.

Pompeii answered 5/10, 2022 at 18:41 Comment(0)
L
0
  1. To create a class off a json string, copy the string.

  2. In Visual Studio, in the menu at the top, click Edit > Paste special > Paste Json as classes.

  3. Install Newtonsoft.Json via Nuget

  4. Paste the following code into your project, "jsonString" being the variable you want to deserialize :

    Rootobject r = Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(jsonString);

  5. Don't forget to rename Rootobject to be more descriptive eg ILoveTheSmellOfNapalmInTheMorning-that was a joke

Lecialecithin answered 20/3 at 19:6 Comment(0)
M
0

Another idea is to use IConfiguration.

This is used -among other things- to read the AppSettings.json. It converts the json-path into keys to construct a Dictionary<string, string>.

In the provided samples

  • the null values are removed
  • the separator is changed from ":" to "."

This code is used and tested in .Net 6.

Sample without sections:

IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(<Your JsonFile>);
IConfigurationRoot configuration = builder.Build();

Dictionary<string, string> tree = configuration
                .AsEnumerable()
                .Where(x => x.Value != null)
                .ToDictionary(x => x.Key.Replace(":", "."), x => x.Value);

Sample with sections (allows to only convert a part of the json):

IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(<Your JsonFile>);
IConfigurationRoot configuration = builder.Build();
IConfigurationSection section = configuration.GetSection("MyData");    

Dictionary<string, string> tree = section
                .AsEnumerable()
                .Where(x => x.Value != null)
                .ToDictionary(x => x.Key.Replace(":", "."), x => x.Value);
Marymarya answered 9/4 at 8:51 Comment(0)
W
-1

I think the best answer that I've seen has been @MD_Sayem_Ahmed.

Your question is "How can I parse Json with C#", but it seems like you are wanting to decode Json. If you are wanting to decode it, Ahmed's answer is good.

If you are trying to accomplish this in ASP.NET Web Api, the easiest way is to create a data transfer object that holds the data you want to assign:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

You have simply add the application/json header to your request (if you are using Fiddler, for example). You would then use this in ASP.NET Web API as follows:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

This helped me a lot when I was working in my Web Api and made my life super easy.

Westward answered 1/6, 2016 at 18:11 Comment(0)
S
-1
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();
Sunnysunproof answered 28/6, 2019 at 18:28 Comment(1)

© 2022 - 2024 — McMap. All rights reserved.