Using Newtonsoft JsonConvert to serialize and deserialize simple class - c#

I'm trying to simply serialize and deserialize a simple class with JsonConvert.SerializeObject(obj) and JsonConvert.DeserializeObject(string).
I'm using this in a custom TypeConverter for a QueryParameter in .NET Web API Core 2.1.
But I'm getting very strange behavior. My class looks like this:
public class ListRequestDto {
public bool? WithCreator { get; set; }
public int? Skip { get; set; }
public int? Limit { get; set; }
}
And I'm trying to do the following:
var test = new ListRequestDto {
WithCreator = true,
Skip = 0,
Limit = 15
};
string ttt = JsonConvert.SerializeObject(test);
But I'm getting the following output:
"MyNameSpace.ListRequestDto"
If I try it the other way around:
string json = "{ WithCreator: true, Skip: 0, Limit: 15 }";
JsonConvert.DeserializeObject<ListRequestDto>(json);
I get the following exception:
Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'MyNameSpace.ListRequestDto' because the type requires a JSON string value to deserialize correctly.
To fix this error either change the JSON to a JSON string value or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'Skip', line 1, position 8."
I tried to remove the nullable fields (replacing them with regular primitives) but that resulted int he exact same error.
The strange thing is, that if I provide the same class as a body it works. And as far as I know Web API Core also uses the Newtonsoft Json Parser.

I do not know why it is necessary, but when I put [JsonObject] on my class it suddenly works.
The exception actually told me to do that, but I do not understand why it is necessary when in no documentation this is used in such a case.
So bascially doing the following solved the problem:
[JsonObject]
public class ListRequestDto {
public bool? WithCreator { get; set; }
public int? Skip { get; set; }
public int? Limit { get; set; }
}

Related

newtonsoft deserialize group of objects

TL;DR
How do I convert json data that looks like this into a C# object using Newtonsoft.json and JsonConvert.DeserializeObject?
{"start":true,"result":{"label":"Setup Account","item":"name"}}
{"start":false,"result":{"label":"Change Account","item":"address"}}
{"start":false,"result":{"label":"Close Account","item":"account"}}
I am trying to deserialize some json exported from Splunk. The data does not look like an array, but rather a list of json objects between {}. Here are the first three objects of 600+ so you can see the format. The first one is actually the Splunk output. I shortened the "Search" in the next two.
{"preview":false,"result":{"label":"Internal Admin Nav","search":"<view isVisible=\"false\" >\n <label>Internal Admin Nav<\/label>\n <module name=\"Message\" layoutPanel=\"messaging\">\n <param name=\"filter\">*<\/param>\n <param name=\"clearOnJobDispatch\">False<\/param>\n <param name=\"maxSize\">1<\/param>\n <\/module>\n <module name=\"AccountBar\" layoutPanel=\"appHeader\">\n <param name=\"mode\">lite<\/param>\n <\/module>\n <module name=\"LiteBar\" layoutPanel=\"liteHeader\"><\/module>\n<\/view>"}}
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}}
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}
If I try to create a class by pasting the first three lines into Visual Studio using Paste Special|Paste JSON as Classes, it complains that it is not Json data (Notepad++ seems to think it is though). If I just paste one of them {"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}} I get this object:
public class Rootobject
{
public bool preview { get; set; }
public Result result { get; set; }
}
public class Result
{
public string label { get; set; }
public string search { get; set; }
}
I have tied to deserialize in many ways.
Rootobject jsonObj = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText(fileName));
Error: Additional text encountered after finished reading JSON content:
List<Rootobject> jsonObj = JsonConvert.DeserializeObject<List<Rootobject>>(File.ReadAllText(fileName));
Error: Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ChecSourcetypes.Program+ObjClass]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'preview', line 1, position 11.'
This is the most promising one and I tried to force it to deserialize by using a JsonObjectAttribute, but that just raised more problems.
I also added this class
public class RootRootobject
{
public List<Rootobject> objects { get; set; }
}
and then used this:
RootRootobject jsonObj = JsonConvert.DeserializeObject<RootRootobject>(File.ReadAllText(fileName));
I have messed with List<> and different objects without any success. I even converted the data to look like this:
[{"preview":false,"result":{"label":"Internal Admin Nav","search":"CCC"}},
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}},
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}]
How do I read this json into an object? I would not want to change the Splunk output, but I could. I also would like to do it using JsonConvert.DeserializeObject. I recall doing this with Splunk data a few years ago using List<>, but do not remember how.
Thanks.
you have to fix your json to this (actually your last case)
[{"preview":false,"result":{"label":"Internal Admin Nav","search":"CCC"}},
{"preview":false,"result":{"label":"Setup Account","search":"AAAA"}},
{"preview":false,"result":{"label":"Contactless Dashboard","search":"BBBB"}}]
use your first classes
public class Rootobject
{
public bool preview { get; set; }
public Result result { get; set; }
}
and this code
List<RootRootobject> jsonObj = JsonConvert.DeserializeObject<List<RootRootobject>>(yourFixedJson);

How can I deserialize this specific json string?

I am trying to deserialize the following json string using Newtonsoft Json. I am able to get the string successfully, but when I try using JsonConvert.DeserializeObject<ServerList>(response, settings);, the try catch fails.
[
{"endpoint":"127.0.0.1","id":6,"identifiers":["steam:","license:","xbl:","live:","discord:"],"name":"Blurr","ping":160},
{"endpoint":"127.0.0.1","id":7,"identifiers":["steam:","license:","xbl:","live:","discord:"],"name":"Knight","ping":120}
]
I believe my issue is because the players array being unnamed.
I have tried [JsonProperty("")] and [JsonProperty] for the Users var, I have also tried using List and Array instead of IList.
Here is the object. This may be completely wrong, I have tried many ways of doing this.
public class ServerList
{
// I have tried many ways of doing this array/list. This is just the latest way I tried.
[JsonProperty]
public static IList<Player> Users { get; set; }
}
public class Player
{
[JsonProperty("endpoint")]
public static string Endpoint { get; set; }
[JsonProperty("id")]
public static string ServerId { get; set; }
[JsonProperty("identifiers")]
public static IList<string> Identifiers { get; set; }
[JsonProperty("name")]
public static string Name { get; set; }
[JsonProperty("ping")]
public static int Ping { get; set; }
}
I am expecting to get a 'ServerList' object returned with a list of all the players connected to the server.
Ask any questions you need to, I don't often work with json in this format. Thank you in advance!
ERROR: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
Simplest way: Your json is an array, so deserialize to an array:
JsonConvert.DeserializeObject<Player[]>(response,settings);
As noted in the comments, properties on the Player should not be static.
If you insist on an object structure similar to what you posted, an object with a Usersproperty, even though it's not present in the JSON, that is also possible, by implementing a custom JSON converter. There's an article with an example of that here: https://www.jerriepelser.com/blog/custom-converters-in-json-net-case-study-1/
HOWEVER; I would recommend sticking to the types present in the json, and perhaps later construct the object that makes sense to the model in your program. This way, what you deserialize are true to the json you are getting, but make no sacrifices on the model you'd like:
var players = JsonConvert.DeserializeObject<Player[]>(response,settings);
var serverList = new ServerList {Users = players};

How to convert JSON Response to a List in C#?

This might be a basic question but I am stuck while converting a JSON Response to a List.
I am getting the JSON Response as,
{"data":[{"ID":"1","Name":"ABC"},{"ID":"2","Name":"DEF"}]}
Have defined a Class,
class Details
{
public List<Company> data { get; set; }
}
class Company
{
public string ID { get; set; }
public string Name { get; set; }
}
Have tried this for converting,
List<Details> obj=List<Details>)JsonConvert.DeserializeObject
(responseString, typeof(List<Details>));
But this returns an error, saying
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Client.Details]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Kindly help!
You don't have a List<Detail> defined in your JSON. Your JSON defines one Detail record, which itself has a list of companies.
Just deserialize using Details as the type, not List<Details> (or, if possible, make the JSON wrap the single detail record into a one item array).
You need to Deserialize like this:
var Jsonobject = JsonConvert.DeserializeObject<Details>(json);
using classes generated by json2csharp.com:
var Jsonobject = JsonConvert.DeserializeObject<RootObject>(json);
and your classes should be :
public class Datum
{
public string ID { get; set; }
public string Name { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
}
you can always use json2csharp.com to generate right classes for the json.
You can use JavaScriptDeserializer class
string json = #"{""data"":[{""ID"":""1"",""Name"":""ABC""},{""ID"":""2"",""Name"":""DEF""}]}";
Details details = new JavaScriptSerializer().Deserialize<Details>(json);
EDIT: yes, there's nothing wrong with OP's approach, and Servy's answer is correct. You should deserialize not as the List of objects but as the type that contains that List

How to convert a Json string to a class that has a list in Json.Net with C# when the json has an array one level deeper

I have a C# Application in which I am using Json.Net from Nuget.
I get a json from my server which I need to convert into a C# object and with a few modifications I will send it back to the server as json.
Here's my model in C# (which I got after converting the server xsd)
public class Tags
{
public List<Tag> tagData { get; set; }
}
public class Tag
{
public string name {get; set;}
}
Here's my JSON string that is obtained from the server and an attempt at conversion to my model
//Json string obtained from server (hardcoded here for simplicity)
string json = "{tagData: {tags : [ { name : \"John\"}, { name : \"Sherlock\"}]}}";
//An attempt at conversion
var output = JsonConvert.DeserializeObject<Tags>(json);
This is the exception I get with the above code
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[jsonnetExample.Tag]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'tagData.tags', line 1, position 17.
After understanding the above message I tried the following 2 things in the hope of fixing it.
A.I tried putting a JsonProperty to my first model.
[JsonProperty(PropertyName = "tags")]
This didn't throw the exception anymore but the output tagData was null.
B. I modified my model as follows
public class Tags
{
public WrapTag tagData { get; set; }
}
public class WrapTag
{
public List<Tag> tags { get; set; }
}
public class Tag
{
public string name {get; set;}
}
This didn't throw any exception and populated the objects as expected. But Now I lost the one to one mapping between xsd(classes from the server) to my client model classes. Is it possible to get this deserialization working without the creation of the WrapTag class?
I would be very glad if someone can point me in the right direction.
Thanks in advance.
Here's one option, using JObject.Parse:
string json = "{tagData: {tags : [ { name : \"John\"}, { name : \"Sherlock\"}]}}";
List<Tag> tagList = JObject.Parse(json)["tagData"]["tags"].ToObject<List<Tag>>();
// or:
// List<Tag> tagList = JObject.Parse(json).SelectToken("tagData.tags")
// .ToObject<List<Tag>>();
Tags tags = new Tags { tagData = tagList };

Deserialize Dictionary with JSON.NET

I am using Newtonsoft.Json with version 4.0.8 and trying to use it with Web API.
So I wanted to deserialize JSON with
JsonConvert.DeserializeObject<AClass>(jsonString);
This works until I added a Dictionary as property to this class and wanted to deserialize it.
The json string is in the form of
{
"Date":null,
"AString":"message",
"Attributes":[
{"Key":"key1","Value":"value1"},
{"Key":"key2","Value":"value2"}
],
"Id":0,
"Description":"...
}
When deserializing exception of type JsonSerializationException occures with message: "Cannot deserialize JSON array into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]'."
What am I doing wrong here?
UPDATE1:
When serializing with JSON.NET i get the following for the dictionary:
Attributes":{"key1":"value1","key2":"value2"}
Seems that WebApi deserializes the object in an other way than Json.Net would.
Server side I use following line for implicit deserializing:
return new HttpResponseMessage<AClass>(object);
UPDATE2:
As a workaround I came now to following line server side.
return new HttpResponseMessage<string>(JsonConvert.SerializeObject(license).Base64Encode());
I convert it with Json.Net server side and transfer it as base64 encoded string. So Json.Net can deserialize its own format.
But its still not that what I want, so are thery any further suggestions?
It should work if you declare Attributes as List<KeyValuePair<string, string>>
From this post, calling
JsonConvert.SerializeObject(yourObject, new KeyValuePairConverter());
gets your JSON in the format that the Web API is creating for you.
Ergo, one might assume that calling
JsonConvert.DeserializeObject<AClass>(jsonString, new KeyValuePairConverter());
will do the reverse and correctly handle the Web API's style.
I have no idea whether this overload even exists, though; give it a try and see what happens...
Dictionary<string, object> result = JsonConvert.DeserializeObject<Dictionary<string, object>>(strJsonResult);
If it's .NET 4, you can use DataContract attributes and the DataContractJsonSerializer Class to enforce the message format:
[DataContract]
public class Message
{
[DataMember]
public DateTime? Date { get; set; }
[DataMember]
public string AString { get; set; }
[DataMember]
public Dictionary<string, string> Attributes { get; set; }
[DataMember]
public int Id { get; set; }
[DataMember]
public string Description { get; set; }
}
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Message));
Message message = null;
using (MemoryStream jsonStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
// Deserialize
message = (Message)jsonSerializer.ReadObject(jsonStream);
// Go to the beginning and discard the current stream contents.
jsonStream.Seek(0, SeekOrigin.Begin);
jsonStream.SetLength(0);
// Serialize
jsonSerializer.WriteObject(jsonStream, message);
jsonString = Encoding.UTF8.GetString(jsonStream.ToArray());
}
Serializing this back out produces the following JSON:
{"AString":"message","Attributes":[{"Key":"key1","Value":"value1"},{"Key":"key2","Value":"value2"}],"Date":null,"Description":"...","Id":0}

Categories