We have a project which using System.Text.Json in .NET 5 instead of Newtonsoft JObject. Using Newtonsoft, it is pretty easy to replace dynamic JSON data e.g. as shown below:
siteDataObject["student"] = JArray.FromObject(studentservice.GetStudents());
When studentservice.GetStudents() is return List as below structure
internal class Student {
public int Id { get; set; }
public string Name { get; set; }
public string ContactPhone { get; set; }
public IEnumerable<MedicalRecord> MedicalRecords { get; set; }
}
internal class MedicalRecord {
public int Id { get; set; }
public string Name { get; set; }
public DateTime RecordDate { get; set; }
public IEnumerable<DiseaseLog> DiseaseLogs{ get; set; }
}
internal class DiseaseLog {
public int Id { get; set; }
public string Name { get; set; }
public DateTime LogDate { get; set; }
}
but in System.Text.Json
foreach (var element in doc.RootElement.EnumerateObject()) {
if (element.Name == "student") {
writer.WritePropertyName(element.Name);
}
else {
element.WriteTo(writer);
}
}
I don't know how to convert List<student> into JSON array data, when student class have many properties with multi collection inside.
Can anyone advise how to convert it ?
To clarify, I need to propose the full code for this, I have a dynamic json string and want to replace element : students into new record, the code will be
var dynamicJson = #"{'roomid':1,'roomcode':'Code001','students':[1],'contentdata':'say hello','footerdata':'cookie policy'}";
using MemoryStream stream = new MemoryStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(stream);
using var dynamicDocument = JsonDocument.Parse(dynamicJson);
writer.WriteStartObject();
foreach (var element in dynamicDocument.RootElement.EnumerateObject())
{
if (element.Name == "students")
{
// unknown how to modify the student record into array
}
else
element.WriteTo(writer);
}
writer.WriteEndObject();
stream.Flush();
var modifyJson = Encoding.UTF8.GetString(stream.ToArray());
I know how to modify student value , if student element is string, but I don't know how to modify it into array, by using simple code. As student have multi class inside.
My expected result should be
{
"roomid": 1,
"roomcode": "Code001",
"students": [
{
"id": 1,
"Name": "Wilson",
"ContactPhone": "123-122-3311",
"MedicalRecords": [
{
"id": 101,
"Name ": "Medial record 101011",
"RecordDate": "2021-12-31",
"DiseaseLogs": [
{
"id": 18211,
"Name ": "Patient Log 19292",
"LogDate": "2020-1-31"
},
{
"id": 18212,
"Name ": "Patient Log 2911w",
"LogDate": "2020-3-31"
}
]
}
]
}
],
"contentdata": "say hello",
"footerdata": "cookie policy"
}
In .NET 5 there is no modifiable JSON Document Object Model built into to System.Text.Json. JsonDocument is read-only, and System.Text.Json.Nodes was only introduced in .NET 6. Thus, the easiest way to deserialize, modify and re-serialize free-form JSON in .NET 5 is to deserialize to some partial data model, with unknown values bound into a dictionary.
If you do not care about the order of properties at the root level, you could deserialize to a model with a public object students { get; set; } property, and bind the remaining elements to a JsonExtensionData overflow dictionary:
public class RootObject
{
public object students { get; set; }
[System.Text.Json.Serialization.JsonExtensionDataAttribute]
public IDictionary<string, object> ExtensionData { get; set; }
}
Then deserialize, modify and re-serialize as follows:
var students = new List<Student> { /* Initialize these as required... */ };
var dynamicJson = #"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";
var root = JsonSerializer.Deserialize<RootObject>(dynamicJson);
root.students = students;
var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });
Which results in
{
"students": [
{
"id": 1,
"name": "Wilson",
"contactPhone": "123-122-3311",
"medicalRecords": [
{
"id": 101,
"name": "Medial record 101011",
"recordDate": "2021-12-31T00:00:00",
"diseaseLogs": [
{
"id": 18211,
"name": "Patient Log 19292",
"logDate": "2020-01-31T00:00:00"
},
{
"id": 18212,
"name": "Patient Log 2911w",
"logDate": "2020-03-31T00:00:00"
}
]
}
]
}
],
"roomid": 1,
"roomcode": "Code001",
"contentdata": "say hello",
"footerdata": "cookie policy"
}
the students property must be declared as object because the input JSON already has an array containing a single integer value; declaring it as public List<Student> students { get; set; } would result in a deserialization when initially loading the JSON.
Demo fiddle #1 here.
If you do care about the order of properties at the root level, you could deserialize to an OrderedDictionary (an old order-preserving non-generic dictionary dating from .NET Framework 2.0 which is still around and supported), overwrite the "students" value, and re-serialize:
var students = new List<Student> { /* Initialize these as required... */ };
var dynamicJson = #"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";
var root = JsonSerializer.Deserialize<OrderedDictionary>(dynamicJson);
root["students"] = students;
var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });
Which results in
{
"roomid": 1,
"roomcode": "Code001",
"students": [
{
"id": 1,
"name": "Wilson",
"contactPhone": "123-122-3311",
"medicalRecords": [
{
"id": 101,
"name": "Medial record 101011",
"recordDate": "2021-12-31T00:00:00",
"diseaseLogs": [
{
"id": 18211,
"name": "Patient Log 19292",
"logDate": "2020-01-31T00:00:00"
},
{
"id": 18212,
"name": "Patient Log 2911w",
"logDate": "2020-03-31T00:00:00"
}
]
}
]
}
],
"contentdata": "say hello",
"footerdata": "cookie policy"
}
Demo fiddle #2 here.
In .NET 6 this all becomes easier through use of the System.Text.Json.Nodes editable JSON Document Object Model:
var dynamicJson = #"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";
var nodes = JsonSerializer.Deserialize<JsonObject>(dynamicJson);
nodes["students"] = JsonSerializer.SerializeToNode(students, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
var modifyJson = nodes.ToString();
But in .NET 5 this is not possible. Demo fiddle #3 here.
I think this is what you want (array or single nested object):
var student = new Student()
{
Name = "Student",
ContactPhone = "contact",
Id = 1,
MedicalRecords = new List<MedicalRecord>()
{
new MedicalRecord()
{
Name = "Medical Record 1",
RecordDate= DateTime.Now ,
Id = 1 ,
MedicalRecords = new List<DiseaseLog>()
{
new DiseaseLog(){ Name = "some disease" ,
LogDate = DateTime.Now, Id =1 }
}
}
}
};
var data = System.Text.Json.JsonSerializer.Serialize(student);
Console.WriteLine(data);
var list = new List<Student>();
list.Add(student);
var arrayData = System.Text.Json.JsonSerializer.Serialize(list);
Console.WriteLine(arrayData);
I have simple class
class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public List<string> ParentsNames { get; set; }
}
And a json file
[
{
"Name": "Frank",
"Surname": "Wilson",
"Age": "52",
"Login": "fwillock",
"Password": "willock123",
"ParentsNames": [
"Charles",
"Sarah"
]
},
{
"Name": "Karen",
"Surname": "Davies",
"Age": "35",
"Login": "kdavies",
"Password": "davies123",
"ParentsNames": [
"Jason",
"Angela"
]
}
]
I need to get in console all names or surnames, existing in Person list. I tried to use something like this:
var JsonDeserialize = File.ReadAllText(fileName);
List<Person> result = JsonSerializer.Deserialize<List<Person>>(JsonDeserialize);
Console.WriteLine(result.Select(x => x.Name).ToList());
But i don't have any idea to use it in my code.
Thanks in advance.
list of names
var names= result.Select(i=> new {Name=i.Name, Surname=i.Surname}).ToList();
to print
foreach (var n in result) Console.WriteLine ( $"{n.Name} {n.Surname}");
If you want to customise how you display information in a class one option is to override ToString() for your Person class:
class Person
{
...
// customize however you like
public override string ToString() => $"{Name} {Surname}";
}
Then to display in a single line, you could use string.Join():
Console.WriteLine(string.Join(", ", result));
Or if you want each person on a new line:
result.ForEach(person => Console.WriteLine(person));
// which can be shortened to
result.ForEach(Console.WriteLine);
I have a two json objects like this below,
Json 1:
{
"data": {
"firstName": "xxx",
"lastName": "yyy",
"age": "29"
}
}
Json 2:
{
"data": {
"firstName": "aaa",
"lastName": "yyy",
"age": "30",
"location": "USA"
},
"meta": {
"browser": "chrome",
"ip": "999.999.999"
}
}
How can i compare properties of json 1 with json 2 and return the bool value if values are equal ?
From the above example the firstName value is different in both json objects so the result will return bool value as false , otherwise it will return true.
Please help, thanks in advance !!!
Approach #1 - Using JObject from Newtonsoft.Json Library
var json1 = File.ReadAllText("json1.json");
var json2 = File.ReadAllText("json2.json");
var jObj1 = JObject.Parse(json1);
var jObj2 = JObject.Parse(json2);
if (jObj1["data"]["firstName"] != null && jObj2["data"]["firstName"] != null && jObj1["data"]["firstName"].ToString() == jObj2["data"]["firstName"].ToString())
{
//condition is true
Console.WriteLine("true");
}
else
{
//condition is false
Console.WriteLine("false");
}
Approach #2 - Using Modal & JsonConvert from Newtonsoft.Json Library. I have used json2csharp to convert the json to c# class
public class Data
{
public string firstName { get; set; }
public string lastName { get; set; }
public string age { get; set; }
public string location { get; set; }
}
public class Meta
{
public string browser { get; set; }
public string ip { get; set; }
}
public class Root
{
public Data data { get; set; }
public Meta meta { get; set; }
}
var jObj1 = JsonConvert.DeserializeObject<Root>(json1);
var jObj2 = JsonConvert.DeserializeObject<Root>(json2);
if (jObj1.data.firstName.Equals(jObj2.data.firstName))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
I am trying to instantiate a poco object with data in a .json file in my VS project. When I use this code, it just returns an empty object.
Class:
public class Person
{
public int id { get; set; }
public string name { get; set; }
}
Json text in in file:
{
"person":
{
"id": 1,
"name": "joe"
}
}
Code in Program.cs:
static void Main(string[] args)
{
string jspath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), #"Json\json1.json");
//person object results in 0 for id and null for name (empty)
Person person = new JavaScriptSerializer().Deserialize<Person>(File.ReadAllText(jspath ));
}
What am I doing wrong?
Your JSON file is not correct.
It should be:
{ "id": 1, "name": "joe" }
Proof:
Person p = new Person
{
id = 1,
name = "joe"
};
var sb = new StringBuilder();
new JavaScriptSerializer().Serialize(p, sb);
Console.WriteLine(sb.ToString()); // Outputs: { "id": 1, "name": "joe" }
I have tried to prevent the property of type object with no new values assigned to its properties using ShouldSerialize Method in Newtonsoft.Json. But I dont know how to implement it, so please help me to solve this...
Here is the sample code
public class Sample1
{
public String name{get;set;}
public int Id{get;set;};
}
And this is my Class containing the above class as one of its properties
public class Container
{
public String Cname{get;set;}
public Sample1 Sample{get;set;};
public bool ShouldSerializeSample()
{
//What should I write here to prevent the Sample property from being serialized when its properties are assigned no new values.
}
}
Given your example classes, I think you you are looking for something like this:
public bool ShouldSerializeSample()
{
return (Sample != null && (Sample.Id != 0 || Sample.name != null));
}
Here is a working demo:
class Program
{
static void Main(string[] args)
{
List<Container> list = new List<Container>
{
new Container
{
Cname = "Will serialize Sample because it has a name",
Sample = new Sample1 { name = "sample 1" }
},
new Container
{
Cname = "Will serialize Sample because it has a non-zero Id",
Sample = new Sample1 { Id = 2 }
},
new Container
{
Cname = "Will serialize Sample because it has a name and an Id",
Sample = new Sample1 { name = "sample 3", Id = 3 }
},
new Container
{
Cname = "Will not serialize Sample because it has default values",
Sample = new Sample1()
},
new Container
{
Cname = "Will not serialize Sample because it is null",
Sample = null
}
};
string json = JsonConvert.SerializeObject(list, Formatting.Indented);
Console.WriteLine(json);
}
}
public class Sample1
{
public String name { get; set; }
public int Id { get; set; }
}
public class Container
{
public String Cname { get; set; }
public Sample1 Sample { get; set; }
public bool ShouldSerializeSample()
{
return (Sample != null && (Sample.Id != 0 || Sample.name != null));
}
}
Here is the output:
[
{
"Cname": "Will serialize Sample because it has a name",
"Sample": {
"name": "sample 1",
"Id": 0
}
},
{
"Cname": "Will serialize Sample because it has a non-zero Id",
"Sample": {
"name": null,
"Id": 2
}
},
{
"Cname": "Will serialize Sample because it has a name and an Id",
"Sample": {
"name": "sample 3",
"Id": 3
}
},
{
"Cname": "Will not serialize Sample because it has default values"
},
{
"Cname": "Will not serialize Sample because it is null"
}
]