How to deserialize an object in ASP.NET? - c#

I am trying to deserialize an object that an API sends me, but when doing so I cannot extract the values.
My object as JSON looks like this:
{
"Obj":
{
"id":19,
"name":"test",
"email":"test#mail.com",
"password":"0439434dae91c10c3bc073af1e76addf8f57a30ce0a7de0438b3aaad34b85200d41d01078f2ee786b3130b4ed4e39e3e26090da5d9f87420454dfdd182761cce",
"city":"Texas",
"age":37,
"date":"2022-05-09T00:00:00",
"mp":0,
"du":0,
"active":false,
"userid":0,
"user":""
},
"message":null,
"error":false,
"information":
{
"menssages":"Ok, Results",
"error":false,
"success":true,
"userId":0,
"user":"",
"register":0,
"pages":0
}
}
My code:
result = GetWebRequest("api/ClientId/" + id);
object rest = new JavaScriptSerializer().DeserializeObject(result.ToString());
Dictionary<string, object> keys = (Dictionary<string, object>)((object)rest);

I'd suggest using JSON.Net for both performance as well as features.
var account = JsonConvert.DeserializeObject<Account>(jsonString);
If you're using ASP.NET Core (not quite clear from your question/tags), you can also use the built-in System.Text.Json:
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Both approaches are much cleaner as you're working with classes instead of a Dictionary. Not that a Dictionary is wrong in any sense, this is just not an optimal use case for it, in particular because you're dealing with nested instances. Though in general, typed access to the properties of your data is almost always a preferred solution.

Related

.NET Core 6, Options Pattern, how to get array of json objects from appsettings

This particular set up continues to elude me. I'm on .NET Core 6, so all of the set up stuff is gone. I'm left with the code below (I think). I have a json array of objects. I've seen where people say that this is a dictionary, so I've tried this, but the values within the array don't populate.
I'm able to get simpler objects to populate their values. I've also tried this pattern according to other SO posts, but no dice.
I keep getting close, but no cigar - What am I doing wrong?
Appsettings.json:
"TimeSlotMenuIds": [
{
"FounderWallEvening": 900000000001136943
},
{
"BravoClubEvening": 900000000001136975
}
]
My mapping class:
public class TimeSlotMenuIds
{
public Dictionary<string, long> TimeSlotMenuId { get; set; }
}
The thing that doesn't populate the values from my json file:
var test = _configuration.GetSection("TimeSlotMenuIds").Get<TimeSlotMenuIds[]>();
var t2 = _configuration.GetSection("TimeSlotMenuIds").GetChildren();
Your JSON structure doesn't really lend itself to being deserialised as a Dictionary directly, instead it would work as an array of dictionaries e.g. Dictionary<string, long>[]. I'm sure you don't want this, so an option would be to manually process the configuration:
var test = Configuration.GetSection("TimeSlotMenuIds")
.GetChildren()
.ToDictionary(
x => x.GetChildren().First().Key,
x => long.Parse(x.GetChildren().First().Value));
Though I would suggest this is a nasty hack. Instead, you should fix the JSON to something like this:
"TimeSlotMenuIds": {
"FounderWallEvening": 900000000001136943,
"BravoClubEvening": 900000000001136975
}
Which would then allow you to do this:
var test = Configuration.GetSection("TimeSlotMenuIds").Get<Dictionary<string, long>>();

Adding data of type dynamic to dictionary

I have a code like this:
private void CreateRecord(dynamic dealerData, string methodVerb)
{
var sample = new MarketData()
{
Parameters = new Dictionary<string, string>();
}
}
I want to add dealerData to dictionary at runtime.
Can this dictionary initialization be used like this:
Parameters = JsonConvert.DeserializeObject<Dictionary<string,string>>(dealerData);
Also, I want to add one more line to this dictionary at runtime.
This is: "Verb", "PUT".
Based on the information provided, it seems like it would be easier - and better practice - to deserialize your Json into a data model. The concept you've come up with doesn't seem to be suited to holding the information you want in an easily usable way.
However, if you insist on pursuing this method, I'll assume your Json looks like:
{ "property1": "value1", "property2": "value2" }
You can deserialize your Json to a Dictionary like this:
Parameters = JsonConvert.DeserializeObject<Dictionary<string,string>>(dealerData);
Parameters.Add("Verb", methodVerb);
If your Json isn't in this format, you'll have to let me know and I'll update my answer.

Parse the JSON string in the ASP.NET

I mostly work on the PHP , recently have switched to ASP.NET,
When parse the JSON, I can simply use -> to get the field, e.g.
foreach(json_decode($_POST['mandrill_events']) as $event) {
$event = $event->event;
$email_type = $event->msg->metadata->email_type;
}
However, in ASP.NET , there is no action, this is my attempt code
var post_data = Request.Form["mandrill_events"];
JavaScriptSerializer ser = new JavaScriptSerializer();
var post_data_json = ser.Deserialize<Dictionary<string, string>>(post_data);
foreach (var event_obj in post_data_json) {
//how to parse the event_obj?
}
Thanks a lot for helping.
use Newtonsoft Json.NET
JsonConvert.DeserializeObject<DataModel>(json);
Unless you want to write a C# class that represents the JSON you are POSTing (the safest solution), you can use the dynamic type to create an object which will look like your JSON. You can then do something like this answer to access the properties.
This solution doesn't give you type safety and the DLR will resolve the properties of the dynamic object at runtime.
As other answers have mentioned, your life will be made much easier by using Newtonsoft JSON which will allow you to write:
dynamic events = JsonConvert.DeserializeObject<dynamic>(post_data);
foreach(dynamic evt in events)
{
string emailType = evt.msg.metadata.email_type;
}

How to receive JSON data into Web API ApiController method?

I'm writing a Web API ApiController with several PUT methods that receive JSON data. The JSON is not deterministic and hence cannot be hard-mapped to a custom C# object, but needs to be received as Dictionaries/Sequences (Maps/Lists).
I have tried using an IDictionary for the data parm of the PUT method in the controller, and this sort of works -- the data appears to be mapped from JSON to the dictionary. However, it's necessary to declare the dictionary as <String,Object>, and there's no clear way to then retrieve the Object values as their appropriate types. (I've found a few suggested kluges in my searching, but they are just that.)
There is also a System.Json.JsonObject type which I finally managed to get loaded via NuGet, but when I use that the system does not appear to know how to map the data.
How is this typically done? How do you implement an ApiController method that receives generic JSON?
I can see three basic approaches:
Somehow make Dictionary/Sequence work with Object or some such.
Make something like System.Json.JsonObject work, perhaps by swizzling the routing info.
Receive the JSON as a byte array and then parse explicitly using one of the C# JSON toolkits available.
(As to how dynamic the data is, JSON objects may have missing entries or extraneous entries, and in some cases a particular entry may be represented as either a single JSON value or a JSON array of values. (Where "value" is JSON array, object, string, number, Boolean, or null.) In general, except for the array/not array ambiguity, the relation between keys and value types is known.)
(But I should note that this is a large project and I'll be receiving JSON strings from several other components by other authors. Being able to examine the received type and assert that it's as expected would be quite useful, and may even be necessary from a security standpoint.)
(I should add that I'm a relative novice with C# -- have only been working with it for about 6 months.)
You've got to know what kind of data you're expecting, but I have had success doing this in the past using dynamic typing.
Something like this:
[Test]
public void JsonTester()
{
string json = "{ 'fruit':'banana', 'color':'yellow' }";
dynamic data = JsonConvert.DeserializeObject(json);
string fruit = data["fruit"];
string color = data["color"];
Assert.That(fruit == "banana");
Assert.That(color == "yellow");
}
Edit:
You either need to know the type you want to deserialize to beforehand - in which case you can deserialize it to that type immediately.
Or you can deserialize it to a dynamic type, and then convert it to your static type once you know what you want to do with it.
using Newtonsoft.Json;
using NUnit.Framework;
public class DTO
{
public string Field1;
public int Field2;
}
public class JsonDeserializationTests
{
[Test]
public void JsonCanBeDeserializedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var data = JsonConvert.DeserializeObject<DTO>(json);
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
[Test]
public void JsonCanBeDeserializedToDynamic_AndConvertedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var dynamicData = JsonConvert.DeserializeObject<dynamic>(json);
var data = new DTO { Field1 = dynamicData["Field1"], Field2 = dynamicData["Field2"] };
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
}

Can you Instantiate an Object Instance from JSON in .NET?

Since Object Initializers are very similar to JSON, and now there are Anonymous Types in .NET. It would be cool to be able to take a string, such as JSON, and create an Anonymous Object that represents the JSON string.
Use Object Initializers to create an Anonymous Type:
var person = new {
FirstName = "Chris",
LastName = "Johnson"
};
It would be awesome if you could pass in a string representation of the Object Initializer code (preferably something like JSON) to create an instance of an Anonymous Type with that data.
I don't know if it's possible, since C# isn't dynamic, and the compiler actually converts the Object Initializer and Anonymous Type into strongly typed code that can run. This is explained in this article.
Maybe functionality to take JSON and create a key/value Dictionary with it would work best.
I know you can serialize/deserializer an object to JSON in .NET, but what I'm look for is a way to create an object that is essentially loosely typed, similarly to how JavaScript works.
Does anyone know the best solution for doing this in .NET?
UPDATE: Too clarify the context of why I'm asking this... I was thinking of how C# could better support JSON at the language level (possibly) and I was trying to think of ways that it could be done today, for conceptual reasons. So, I thought I'd post it here to start a discussion.
There are languages for .NET that have duck-typing but it's not possible with C# using Dot.Notation since C# requires that all member references are resolved at compile time. If you want to use the Dot.Notation, you still have to define a class somewhere with the required properties, and use whatever method you want to instantiate the class from the JSON data. Pre-defining a class does have benefits like strong typing, IDE support including intellisense, and not worrying about spelling mistakes. You can still use anonymous types:
T deserialize<T>(string jsonStr, T obj) { /* ... */}
var jsonString = "{FirstName='Chris', LastName='Johnson, Other='unused'}";
var person = deserialize(jsonString, new {FirstName="",LastName=""});
var x = person.FirstName; //strongly-typed
You should check out the JSON.net project:
http://james.newtonking.com/pages/json-net.aspx
You are basically talking about the ability to hydrate an object from JSON, which this will do. It won't do the anonymous types, but maybe it will get you close enough.
I wrote a relatively short method that will Parse JSON and return a name/value Dictionary that can be accessed similarly to the actual object in JavaScript.
Here's a sample usage of the below method:
var obj = ParseJsonToDictionary("{FirstName: \"Chris\", \"Address\":{Street:\"My Street\",Number:123}}");
// Access the Address.Number value
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"];
And, here's the code for the ParseJsonToDictionary method:
public static Dictionary<string, object> ParseJsonToDictionary(string json)
{
var d = new Dictionary<string, object>();
if (json.StartsWith("{"))
{
json = json.Remove(0, 1);
if (json.EndsWith("}"))
json = json.Substring(0, json.Length - 1);
}
json.Trim();
// Parse out Object Properties from JSON
while (json.Length > 0)
{
var beginProp = json.Substring(0, json.IndexOf(':'));
json = json.Substring(beginProp.Length);
var indexOfComma = json.IndexOf(',');
string endProp;
if (indexOfComma > -1)
{
endProp = json.Substring(0, indexOfComma);
json = json.Substring(endProp.Length);
}
else
{
endProp = json;
json = string.Empty;
}
var curlyIndex = endProp.IndexOf('{');
if (curlyIndex > -1)
{
var curlyCount = 1;
while (endProp.Substring(curlyIndex + 1).IndexOf("{") > -1)
{
curlyCount++;
curlyIndex = endProp.Substring(curlyIndex + 1).IndexOf("{");
}
while (curlyCount > 0)
{
endProp += json.Substring(0, json.IndexOf('}') + 1);
json = json.Remove(0, json.IndexOf('}') + 1);
curlyCount--;
}
}
json = json.Trim();
if (json.StartsWith(","))
json = json.Remove(0, 1);
json.Trim();
// Individual Property (Name/Value Pair) Is Isolated
var s = (beginProp + endProp).Trim();
// Now parse the name/value pair out and put into Dictionary
var name = s.Substring(0, s.IndexOf(":")).Trim();
var value = s.Substring(name.Length + 1).Trim();
if (name.StartsWith("\"") && name.EndsWith("\""))
{
name = name.Substring(1, name.Length - 2);
}
double valueNumberCheck;
if (value.StartsWith("\"") && value.StartsWith("\""))
{
// String Value
d.Add(name, value.Substring(1, value.Length - 2));
}
else if (value.StartsWith("{") && value.EndsWith("}"))
{
// JSON Value
d.Add(name, ParseJsonToDictionary(value));
}
else if (double.TryParse(value, out valueNumberCheck))
{
// Numeric Value
d.Add(name, valueNumberCheck);
}
else
d.Add(name, value);
}
return d;
}
I know this method may be a little rough, and it could probably be optimized quite a bit, but it's the first draft and it just works.
Also, before you complain about it not using regular expressions, keep in mind that not everyone really understands regular expressions, and writing it that way would make in more difficult for others to fix if needed. Also, I currently don't know regular expression too well, and string parsing was just easier.
You can't return an anonymous type from a method**, so a "rehydrated" anonymous type's existence would be limited to the method in which it is rehydrated. Kind of pointless.
** You can return it as an object (which requires reflection to access its properties--yeech) or you can "cast it by example", which is pointless as well, since it takes extra steps and it means you already KNOW what the object's type should look like, so why not just create an object and fill it up in the first place?
What is the application for this?
I would not go down this road for a few reasons.
First; it may require a lot of support code using reflection and such to create the transparent method that you are talking about.
Second, like you said, C# is a strongly typed language and things like these were left out of the language specification for a reason.
Third, the overhead for doing this would not be worth it. Remember that web pages (especially AJAX queries) should be really fast or it defeats the purpose. If you go ahead and spend 50% serializing your objects between C# and Javascript then you have a problem.
My solution would be to create a class that just encapsulates a dictionary and that takes a JSON string as a ctor argument. Then just extend that class for each type of JSON query you want to handle. This will be a strongly typed and faster solution but still maintain extensibility and ease of use. The downside is that there is more code to write per type of JSON request.
:)

Categories