For example, I have two Jsons: the first one I gave from Test Constructor, the second I gave such a user result of a test (I'm using the JS libriry - survey.js) :
The First :
{
"pages": [
{
"name": "page 1",
"elements": [
{
"type": "checkbox",
"name": "question 1",
"correctAnswer": [
"item1",
"item3"
],
"choices": [
"item1",
"item2",
"item3"
]
},
{
"type": "radiogroup",
"name": "question 2",
"correctAnswer": "item2",
"choices": [
"item1",
"item2",
"item3"
]
}
]
}
]
}
The Second:
{
"question 1":["item3","item1"],
"question 2":"item2"
}
How should I compare those two Jsons by correctAnswer?
I require result such:
question 1 - wrong,
question 2 - right.
as user gsharp mentioned you can use json.NET to achieve this.
Just do the following: create your classes that will hold the survey form:
public class SurveyForm
{
[JsonProperty("pages")]
public IEnumerable<SurveyPage> Pages { get; set; }
}
public class SurveyPage
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("elements")]
public IEnumerable<SurveyPageElement> Elements { get; set; }
}
public class SurveyPageElement
{
// I think you can do the rest
}
public class SurveyResult
{
// same as the other classes
}
Do you notice the JsonProperty Attribute? Use that to tell json.NET where to find the related properties in your json. You actually don't need to do that because json.NET does some magic to find the correct properties by it's own but I think it is useful to do it by my own.
Then deserialize the two Jsons:
var surveyForm = JsonConvert.DeserializeObject<SurveyForm>(surveyFormJson);
var surveyResult = JsonConvert.DeserializeObject<Dictionary<string,IEnumerable<string>>>(surveyResultJson);
EDIT: To compare the both do something like this:
foreach(var page in surveyForm.Pages)
{
foreach(var element in page.Elements)
{
if(element.CorrectAnswers.All(surveyResult[element.Name].Contains))
{
// right
}
else
{
// wrong
}
}
}
Related
Newbie question. I have a semi-complex JSON file that I have parsed in my program. The relevant parts are below:
{
"version": "36",
"released": "20220223",
"samples": {
"Samp1": [
{
"code": "A01",
"status": "Optimal",
"bestBy": "20210918",
"expires": "20211018",
"elementKeys": {
"H": [
"Hydrogen-std1-slt4"
]
}
},
{
"code": "A02",
"status": "Optimal",
"bestBy": "20211201",
"expires": "20220501",
"elementKeys": {
"H": [
"Hydrogen-std1-slt5"
]
}
},
{
"code": "A03",
"status": "Optimal",
"bestBy": "20230201",
"expires": "20230801",
"elementKeys": {
"H": [
"Hydrogen-std1-slt6"
]
}
}
],
"Samp2": [ ...
"Samp3": [ ...
"Samp4": [ ...
},
"element": {
"Hydrogen-std1-slt4": {
"format": "1.0",
"position": 4,
"standard": "std1",
...
...
}
What I need to do is populate some windows form controls with data from this file. However, thanks to the odd architecture, I'm a little frustrated over how to populate the controls for "code", "status", "bestBy", etc contained within the "samples" arrays (Samp1, 2, 3, and 4).
Only some of the samples are relevant and the relevancy is defined by whether or not the name of the element key is found further below in the JSON file. So, using the example above, within "element", the object "Hydrogen-std1-slt4" is found in the body of the JSON file with its own key-value pairs. I would like the program to see that and recognize that "Hydrogen-std1-slt4" is also found within the object in the "Samp1" array with the code "A01", the status of "Optimal", the best-by date of "20210918", and that it expires on "20211018". Since it isn't found in any other place in "Samp1", the program can ignore the other objects.
What would be the easiest, most logical way to go about making a conditional for that?
try this code
var jsonParsed = JObject.Parse(json);
string[] elementKeys = ((JObject)jsonParsed["element"]).Properties().Select(x => x.Name).ToArray();
List<Samp> data= GetData(((JObject) jsonParsed["samples"]), elementKeys);
public List<Samp> GetData(JObject samples, string[] elementKeys)
{
List<Samp> result = new List<Samp>();
foreach (var element in samples.Properties())
foreach (var item in element.Value)
if ( item["elementKeys"]["H"]!=null
&& item["elementKeys"]["H"].ToObject<string[]>()
.Any(x => elementKeys.Contains(x)) )
result.Add(item.ToObject<Samp>());
return result;
}
classes
public class Samp
{
public string code { get; set; }
public string status { get; set; }
public string bestBy { get; set; }
public string expires { get; set; }
public ElementKeys elementKeys { get; set; }
}
public class ElementKeys
{
public List<string> H { get; set; }
}
I want to deserialize this JSON:
{
"Home1": [
{
"name": "Hans",
"age": 20
},
{...}
],
"Home2": [
{...},
{...}
]
}
into an List<House>
with these classes:
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
class House : List<Person> {
public string Name { get; set; }
}
How can I tell Newtonsoft JSON that House.Name should be for the key (Home1)?
PS: The class structure is not fixed, but I need the name of the house to be a property in a class.
Leaving behind the rational behind the idea of inheriting a list and your class structure you surely can create custom converter but I would argue much easier option would be to deserialize json into Dictionary<string, House> (which can represent your json structure) and then manually map the names:
var result = JsonConvert.DeserializeObject<Dictionary<string, House>>(json);
foreach (var kvp in result)
{
kvp.Value.Name = kvp.Key;
}
var houses = result.Values;
try this
var deserializedJson = JsonConvert.DeserializeObject<Dictionary<string, List<Person>>>(json);
var houses=new List<House>();
foreach (var element in deserializedJson)
{
houses.Add(new House { Name = element.Key, Persons = element.Value} );
}
var result=JsonConvert.SerializeObject(houses);
}
result
[
{
"Name": "Home1",
"Persons": [
{
"Name": "Hans",
"Age": 20
}
]
},
{
"Name": "Home2",
"Persons": [
{
"Name": "John",
"Age": 22
}
]
}
]
classes
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class House
{
public string Name { get; set; }
public List<Person> Persons {get; set;}
}
Json parsing/deserialization doesn't work this way.
You must have the class of same structure, of what the json is.
Your source json is object having property Home1, Home2 etc.
But you directly expecting it to convert into another structure.
I recommend first convert the json in Real object with the structure of json. Then loop through the property and fill it with loop in List.
Also can you please explain what this class is supposed to do.
class House : List<Person> { public string Name { get; set; } }
For me it doesn't make any sense.
An answer based on you requirement,
How about we clean your JSON string before deserializing and spicing it up with REGEX?
string json = #"{
""Home1"": [
{
""name"": ""Hans"",
""age"": 20
},
{
""name"": ""Hans"",
""age"": 20
},
],
""Home2"": [
{
""name"": ""Hans"",
""age"": 20
},
{
""name"": ""Hans"",
""age"": 20
},
]
}";
/*Replaces all Home + Digit combination to Home*/
json = Regex.Replace(json, #"Home\d*", "Home");
/* Output
{
"Home": [
{
"name": "Hans",
"age": 20
},
{
"name": "Hans",
"age": 20
},
],
"Home": [
{
"name": "Hans",
"age": 20
},
{
"name": "Hans",
"age": 20
},
]
}
*/
This question already has answers here:
Json.Net Serialization of Type with Polymorphic Child Object
(3 answers)
Closed 1 year ago.
I have a sample controller when called should return a serialised object with a list of Animals with all there properties dislayed. The trouble im facing is that its only serialising the property in the base class
Model
public class MyAnimals
{
public string Description { get; set; }
public ICollection<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { set; get; }
}
public class Dog: Animal
{
public string Says { get; set; }
}
public class Cat : Animal
{
public string Likes { get; set; }
}
Controller
[HttpGet]
public IActionResult Animals()
{
var animals = new MyAnimals()
{
Description = "My favorite animals",
Animals = new List<Animal>()
{
new Cat()
{
Name = "Tom",
Likes = "Cheese"
},
new Dog()
{
Name = "Pluto",
Says = "Bark"
}
}
};
return Ok(animals);
}
when the object is seralised its coming out like this
Current Response
{
"description": "My favorite animals",
"animals": [
{
"name": "Tom"
},
{
"name": "Pluto"
}
]
}
The required output im after should be like the below. Please tell me what im doing wrong
Required Response
{
"description": "My favorite animals",
"animals": [
{
"name": "Tom",
"Likes": "Cheese"
},
{
"name": "Pluto",
"Says": "Bark"
}
]
}
For a .NET Core 3+ project, you need to install
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
and use it in startup
services.AddControllers().AddNewtonsoftJson();
This will use JSON.NET as default serializer and you can get the desired response
{
"description": "My favorite animals",
"animals": [
{
"likes": "Cheese",
"name": "Tom"
},
{
"says": "Bark",
"name": "Pluto"
}
]
}
Serializing is the first part of your issue, deserializing would be the scond part.
Caleb George and JuanR have pointed you in good direction and a way to solve the problem.
Other way to do that is to manualy serialize each animal and transport it in animals array vith names and values. Name would be type of animal and value serialized object...
I've searched high and low for an exact example for how to populate a <select> control with <optgroup>, but I get various results. The documentation on select2.org states that the format should be like this:
{
"results": [
{
"text": "Group 1",
"children" : [
{
"id": 1,
"text": "Option 1.1"
},
{
"id": 2,
"text": "Option 1.2"
}
]
},
{
"text": "Group 2",
"children" : [
{
"id": 3,
"text": "Option 2.1"
},
{
"id": 4,
"text": "Option 2.2"
}
]
}
],
"pagination": {
"more": true
}
}
But my results throw an error stating that the 'ID' field is not present. I think it's due to the way I'm initializing the <select>, but I don't see another way.
First, my data is being pulled from a MS SQL db using a stored procedure. I don't have easy control over the data format, so I'm using Linq to create an object I then initialize the <select> with using .DataBind(). Here is the relevant code:
HTML:
<select id="MySelect" name="myselect" runat="server"></select>
Definitions for Parent and Child:
public class Parent : Child
{
public List<Child> children { get; set; }
}
public class Child
{
public string id { get; set; }
public string text { get; set; }
}
Linq statement:
var parents = myData
.Select(c => new Parent()
{
text = string.Format("{0} {1}", c.first_name, c.last_name),
id = c.ID.ToString(),
children = GetChildren(locations, c)
})
.ToArray();
// Convert to JSON
var json = JsonConvert.SerializeObject(new
{
results = parents
});
Linq result converted to JSON:
{
"results":[
{
"id":"2",
"text":"Parent 1 ",
"children":[
]
},
{
"id":"39",
"text":"Parent 2",
"children":[
{
"text":"Child 2.1",
"id":"62",
"Custom1":"196.00"
},
{
"text":"Child 2.2",
"id":"130",
"Custom1":"642.00"
},
{
"text":"Child 2.2",
"id":"61",
"Custom1":"0.00"
}
]
},
{
"id":"15",
"text":"Parent 3",
"children":[
{
"text":"Child 3.1",
"id":"13",
"Custom1":"40.00"
}
]
}
]
}
DataBind:
MySelect.DataSource = json;
MySelect.DataValueField = "id";
MySelect.DataTextField = "text";
MySelect.DataBind();
After all of this, the MySelect <select> renders with a dropdown containing only the parents and no <optgroup> elements in the actual HTML.
I have tried excluding the 'id' member from the <Parent> class, but then there is an error thrown from the .DataBind() that there is no 'id' even though the children all have ids.
I suspect that using .DataBind() isn't the way to handle this. I want to keep the code clean, short and quick.
How can I accomplish this?
I'm currently working with the following json structure and I'm not sure how to model it on my classes, since I've never run into this kind of structure before. Would appreciate any leads or help:
{ "messages": { "1": { "tid": "309", "status": "0", "timestamp": "1379795079", "uid": "1111111111", "txt": "sometext" }, "2": { "tid": "310", "status": "0", "timestamp": "1379795523", "uid": "2222222222", "txt": "sometext2" } }, "status": 1 }
The messages value objects are not a common json structure that i know of, I understand that these are objects, but I don't know how to map them with my classes.
I Use json2csharp, to model my objects for me. Consider the following json object:
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }]
}
I get these objects from the tool:
public class Employee
{
public string firstName { get; set; }
public string lastName { get; set; }
}
public class RootObject
{
public List<Employee> employees { get; set; }
}
Source: http://json2csharp.com/
Technically, your json object is a dictionary, associative array or even hash-table (select appropriate for your target language). Such a data structure is a perfectly reasonable thing to serialize.
However, that particular object would probably have been better serialized as something like:
{ "messages":
[
{ "tid": "309"
, "status": "0"
, "timestamp": "1379795079"
, "uid": "1111111111"
, "txt": "sometext"
}
,
{ "tid": "310"
, "status": "0"
, "timestamp": "1379795523"
, "uid": "2222222222"
, "txt": "sometext2" }
}
]
, "status": 1
}
(unless the sender wanted the option of sending the individual messages items out of order). That's certainly how I would represent it.
This is how I've solved it:
public class MessagesResponse
{
[JsonProperty("messages")]
public Dictionary Messages { get; set; }
[JsonProperty("status")]
public int Status { get; set; }
}
THanks to #rici, I've realized that the use of a dictionary would solve the problem