How to de-serialize sub nodes in NewtenSoft from JSON file - c#

I read a JSON file, please see below the current format. De-serialization works as expected. Now the customer has provided me with another file for which the format is slightly different. The application has to accommodate both of these formats in the future.
In the current format I basically read the value replicate field and I have to basically do the same in the new format. In the new format the replicate field is inside a new node called Assays. I am not sure to how read through the sub node.
**Current Format**
"Orders": [
{
"Rack": "0015",
"SampleType": "Calibrator",
"Position": 1,
"CalMaterialLotNumber" : "08559LF00",
"CalMaterialExpirationDate" : "07-31-2012",
"LevelName" : "Cal 1",
"AssayNumber": 149,
"AssayVersion": 5,
"Dilution": 1,
"Replicate": 3,
"Track": 1,
"Lane": 1,
"ReagentMasterLot": "08559LF00",
"ReagentSerialNumber": 65000,
"
**New Format**
{
"MCCOrders": [
{
"Carrier": "Z425",
"Position": 1,
"CalMaterialLotNumber" : "03112I000",
"CalMaterialExpirationDate" : "02-28-2014",
"Assays": [
{
"AssayNumber": 1014,
"AssayVersion": 6,
"Dilution": 1,
"Replicate": 3,
"MasterLotNumber": "03112I000",
"PackSerialNumber": "20001",
"Comment": "TP Cal"
},
Members
public class CategoryTypeColl
{
public CategoryType[] MCCOrders { get; set; }
}
public class CategoryType
{
public int Replicate { get; set; }
}
Method processing the JSON file
public static KeyValuePair<bool, int> CyclesCompleted(string fileName)
{
int cyclesCompleted = 0;
JavaScriptSerializer ser = jss();
bool isValid = true;
try
{
//Run Newtonsoft JSON deserializer
var deserialized = JsonConvert.DeserializeObject<CategoryTypeColl>(LoadTextFromFile(fileName));
CategoryTypeColl ctl = deserialized;
//CategoryTypeColl ctl = ser.Deserialize<CategoryTypeColl>(LoadTextFromFile(fileName));
if (ctl != null)
{
List<CategoryType> collection = (from item in ctl.MCCOrders
select item).ToList();
foreach (var replicates in collection)
{
cyclesCompleted = cyclesCompleted + replicates.Replicate;
}
}
}
catch
{
isValid = false;
}
return new KeyValuePair<bool, int>(isValid, cyclesCompleted);
}

Related

converting enums to json objects

I have two enums:
enum myEnum
{
item_one = 1,
item_two = 2,
}
enum myEnum2
{
item_four = 4,
item_five = 5,
}
I would like to represent these as Json objects so that I can send then off when a http request is made. the goal is to have them look like:
{
myEnum:{[
{
"code": 1, "definition": "item_one"
},
{
"code": 2, "definition": "item_two"
}
]},
myEnum2:{[
{
"code": 4, "definition": "item_four"
},
{
"code": 5, "definition": "item_five"
}
]},
}
I would create an in-between mapping object, that can be put through a serializer like Newtonsoft.Json or System.Text.Json:
// Out mapping object
class EnumMapper {
public int Code { get; set; }
public string Definition { get; set; }
}
// Create the target output format
var result = new Dictionary<string, List<EnumMapper>>();
// Go over an enum and add it to the dictionary
// Should properly be made into a method so it easier to add more enums
foreach(var enumValue in Enum.GetValue(typeof(myEnum))) {
// List containing all values of a single enum
var enumValues = new List<EnumMapper>();
enumValues.Add(new EnumMapper {
Code = (int)enumValue,
Description = Enum.GetName(enumValue)
});
// Add the enum values to the output dictionary
result.Add("myEnum", enumValues)
}
// Serialize to JSON
var json = JsonConvert.Serialize(result)
I haven't tested the above code - but you should be able to grasp the general idea from it.

Equivalent of JArray.FromObject() in .Net5?

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);

Does one array contain any value in the other array Mongodb using c#

{
"objects": [
{
"id": 123,
"tracking_datas": [
{
"id": 1,
"polygons": [1,3]
},
{
"id": 2,
"polygons": [3]
},
{
"id": 3,
"polygons": [1,2]
}
]
}
]
}
I have a json file as above. And there is a model that satisfies this json in my NetCore project. I want to get objects containing polygonIds that I have determined with the help of mongodb. How can I do this with c# mongo db?
For example, I have a reference array requiredPolygons: [1,2] and I want to get the data containing these polygon'ids in the tracking data of the objects in the json. The expected result is as follows.
{
"objects":
[
{
"id": 123,
"tracking_datas":[
{
"id": 1,
"polygons": [1,3]
},
{
"id": 3,
"polygons": [1,2]
}
]
}
]
}
public class Test
{
public ObjectId Id { get; set; }
public IEnumerable<Object> objects { get; set; }
[BsonExtraElements]
public BsonDocument UnmappedFields { get; set; } // I'm not sure why it's required, something wrong with mapping configuration,
// but it's a separate question
}
public class Object
{
public int id { get; set; }
public IEnumerable<TrackingData> tracking_datas { get; set; }
}
public class TrackingData
{
public int id { get; set; }
public IEnumerable<int> polygons { get; set; }
[BsonExtraElements]
public BsonDocument UnmappedFields { get; set; } // I'm not sure why it's required, something wrong with mapping configuration,
// but it's a separate question
}
var json = #"{
""objects"": [
{
""id"": 123,
""tracking_datas"": [
{
""id"": 1,
""polygons"": [1,3]
},
{
""id"": 2,
""polygons"": [3]
},
{
""id"": 3,
""polygons"": [1,2]
}
]
}
]
}";
var client = new MongoClient();
var db = client.GetDatabase("so_test");
var coll = db.GetCollection<BsonDocument>("coll");
coll.InsertOne(BsonDocument.Parse(json));
var ids = new[] { 1, 2 };
var typedColl = db.GetCollection<Test>("coll");
var result = typedColl
.Aggregate()
.Project(p =>
new Test
{
Id = p.Id,
objects = p.objects.Select(o =>
new Object
{
id = o.id,
tracking_datas = o.tracking_datas.Where(t => t.polygons.Any(p=>ids.Contains(p)))
})
}
)
.ToList();
Here you go:
db.collection.find({
"objects.tracking_datas.polygons": {
$in: [
1,
2
]
}
})
https://mongoplayground.net/p/MDlIV3YPkZB

Converting a complex JSON object into a C# property

I am struggling to build a complex JSON object this is what I want:
{"name": [ "failed","complete"], "data": ["failed":[1, 2, 3], "completed": [1, 2, 3]}
I want to convert this in a C# class as a property. There must be a connection with the failed property and the list of int. The output must be:
failed: 1, 2, 3
complete: 1,2 ,3
What is the correct syntax of a JSON object like this? And how can I declare a property of this object in c#?
I was thinking about dictionaries but maybe there is a better way?
Kind regards
I think it should be :
{"name": [ "failed","complete"], "data": {"failed":[1, 2, 3], "completed": [1, 2, 3]}}
then you can use :
public class Data {
public List<int> failed { get; set; }
public List<int> completed { get; set; }
}
public class RootObject {
public List<string> name { get; set; }
public Data data { get; set; }
}
and for any json to c#, I use :
json2csharp.com
EDIT:
I think, a better approach for your case is using dictionary and following class:
public class DataValues {
public List<int> Data;
}
and then use it like :
Dictionary<string, DataValues> x = new Dictionary<string, DataValues>();
x.Add("failed", new DataValues() {
Data = new List<int> { 1, 2, 3 }
});
x.Add("complete", new DataValues() {
Data = new List<int> { 1, 2, 3 }
});
var resultinJson = new JavaScriptSerializer().Serialize(x);
Then, the Json result is :
{
"failed": {
"Data": [1, 2, 3]
},
"complete": {
"Data": [1, 2, 3]
}
}
obviously, you can add more status or step or what ever it is called in your app. to it.

How to parse and read Json formatted text?

I have a File with following formatted Json
{
"Id": 0,
"MsgId": 125,
"ExceptionDetails": "whatever2"
}
{
"Id": 1,
"MsgId": 135,
"ExceptionDetails": "whatever2"
}
THIS IS EXACTLY HOW IT IS IN A FILE WITH NO BRAKETS
I need to parse this text file and get the values of these Keys, for instance in this example I need to get the 0 and 1
var json = System.IO.File.ReadAllText(#"C:\development\commonArea\test3.txt");
var objects = JArray.Parse(json); // parse as array
foreach (JObject root in objects)
{
foreach (KeyValuePair<String, JToken> app in root)
{
if (app.Key == "Id")
{
var appName2 = app.Key;
Console.WriteLine(I HAVE NO IDEA);
}
}
}
Thanks
var objects = JArray.Parse(json); // parse as array
foreach (JObject jobject in objects)
{
Console.WriteLine(jobject.Value<int>("Id"));
}
prints:
0
1
You presented an invalid JSON. I've modified it, so that it became a valid JSON array:
[
{ "Id": 0, "MsgId": 125, "ExceptionDetails": "whatever2" },
{ "Id": 1, "MsgId": 135, "ExceptionDetails": "whatever2" }
]
Make a class that matches and then use a Deserializer. This is using the System.Web.Script.Serialization namespace.
public class Item
{
public int Id { get; set; }
public int MsgId { get; set; }
public string ExceptionDetails { get; set; }
}
public class RootObject
{
public List<Item> Items { get; set; }
public RootObject DeserializeClass()
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
RootObject obj = serializer.Deserialize<RootObject >(JSONSTRING);
return obj;
}
}

Categories