Json modelling issue - c#

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

Related

I want to convert api json data to value c#

Hi i'm newbie in c# dev and i'm not good at english i try to get value from json but it gives error [https://www.tutorialsteacher.com/articles/convert-json-string-to-object-in-csharp]
If anyone can help me with simple code I would be very grateful.
{
"result": [{
"company": "Server",
"results": [{
"name": "Server-01",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-02",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-03",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "1"
}, {
"name": "Server-04",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}, {
"name": "Server-05",
"access": ["8.8.8.8:443", "1.1.1.1:443"],
"is_ok": "0"
}]
}]
}
C# can be different. Like .Net Framework or .Net Core / .Net, so next time please provide which framework do you use.
The are two common ways to deserialize JSON string - Json.NET (3rd party) or System.Text.Json (part of .Net).
For correct deserealization first of all you must provide valid models. But sometimes JSON properties violates C# Naming Conventions or they even can't be represented in code (e.g. property name with whitespace or "is_ok" from your JSON). To avoid this you must to use property attribute that connect your property in code and property in JSON. It's:
[JsonProperty("PropertyName")] for Json.NET
[JsonPropertyName("PropertyName")] for System.Text.Json
So, summing up the above, you must add models similar to this:
public class ResultWrapper
{
[JsonProperty("result")] //use one of it based on selected library
[JsonPropertyName("result")]
public List<Result> Result { get; set; }
}
public class Result
{
[JsonProperty("company")]
[JsonPropertyName("company")]
public string Company { get; set; }
[JsonProperty("results")]
[JsonPropertyName("results")]
public List<ResultItem> Results { get; set; }
}
public class ResultItem
{
[JsonProperty("name")]
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonProperty("access")]
[JsonPropertyName("access")]
public List<string> Access { get; set; }
[JsonProperty("is_ok")]
[JsonPropertyName("is_ok")]
public string IsOk { get; set; }
}
and use one of next deserealization methods:
//Json.Net
var deserializedJsonNet = JsonConvert.DeserializeObject<ResultWrapper>(jsonFromQuestion);
//System.Text.Json
var deserializedSystemTextJson = JsonSerializer.Deserialize<ResultWrapper>(jsonFromQuestion);

Cross-referencing two parts of one JSON file in C#?

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

Create object of json when elements are variables

i need help for deserialize this json on C#.
{
"date": "2021-01-04T16:58:06-03:00",
"resultsInThisPage": 2,
"currentPage": 1,
"totalPages": 1,
"paymentOrders": {
"3AC525B8EF5F413D86CFDC9318E8B3F8": {
"code": "3AC525B8EF5F413D86CFDC9318E8B3F8",
"status": 5,
"amount": 3.00,
"grossAmount": 3,
"lastEventDate": "2021-01-04T16:54:36-03:00",
"schedulingDate": "2021-01-04T16:54:31-03:00",
"transactions": [
{
"code": "AF63C1B13EF14F318C51119CBE1E5CA4",
"date": "2021-01-04T16:54:32-03:00",
"status": 3
}
],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
},
"1E5A8F8D35D34938A12281BD45C62DBE": {
"code": "1E5A8F8D35D34938A12281BD45C62DBE",
"status": 1,
"amount": 3.00,
"grossAmount": 0,
"lastEventDate": "2021-01-04T16:54:33-03:00",
"schedulingDate": "2021-02-04T05:54:31-03:00",
"transactions": [],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
}
}
}
I´m trying use one Class for make this, but the elements of "paymentOrders" are variables.
How is the best way for do this?
I need create a object to manipulate these values.
paymentOrders would be a Dictionary<string,SomeObject> where SomeObject represents the object with all the properties like code, status etc
You can use Dictionary<string, SomeType> (or even Dictionary<Guid, SomeType> in your case, based on provided sample) to represent dynamic property names for paymentOrders json object. Something like this should do the trick:
public class Root {
// your dynamic prop
public Dictionary<string, PaymentOrder> paymentOrders { get; set; }
public DateTime date { get; set; }
// ... the rest o properties
}
public class PaymentOrder {
public string code { get; set; }
public int status { get; set; }
// ... the rest o properties
}

Serialize some relationships to JSON, but not all

I have the following problem: I am trying to serialize an object (object1) to Json using Newtonsoft.Json package. I need to be able to send it to a server. The problem is object1 has several referenced objects, some that should be created together with object1, but one of them is "read only" on the server, so it must be send as a relationship.
I am using string json = JsonConvert.SerializeObject
Example:
<code>
[DataContract]
public class Object1
{
// Simple Properties
[JsonProperty(PropertyName = "ext_ref", Order = 1)]
public string ExtRef { get; set; }
[JsonProperty(PropertyName = "external_comment", Order = 1)]
public string ExternalComment { get; set; }
[JsonProperty(PropertyName = "internal_comment", Order = 1)]
public string InternalComment { get; set; }
[JsonProperty(PropertyName = "object2")]
public Object2 Object2 { get; set; }
[JsonProperty(PropertyName = "object3")]
public Object3 Object3 { get; set; }
}
</code>
This is how I get it atm. This is fine for most of the objects, but not all:
{
"data": {
"attributes": {
"ext_ref": "2573421",
"external_comment": "Ext Comment",
"internal_comment": "Internal comment",
"object2": {
"data": {
"attributes": {
"xx":"XX",
"yy":"YY"
},
"id": "1",
"type": "object2s"
},
"object3": {
"data": {
"attributes": {
"xx":"XX",
"yy":"YY"
},
"id": "1",
"type": "object3s"
}
},
},
"type": "object1"
}
Because the object2 is a "special case", where it can only be understood by the server as a link, it needs to look like this:
{
"data": {
"attributes":{
"ext_ref": "2573421",
"external_comment": "Ext Comment",
"internal_comment": "Internal comment",
"object3": {
"data": {
"attributes": {
"xx":"XX",
"yy":"YY"
},
"id": "1",
"type": "object3s"
}
},
"type": "object1",
"relationships":{
"object2": {
"data": {
"id": "1",
"type": "object2s"
}
}
}
}
Now my question is this: Is there an easy way of doing this?
I have tried the following:
Using the Relationship attribute from JsonApiSerializer
Changing the JsonProperty settings for the object2.id property
Deleting the object2.id
I can't help thinking there must some attribute I can use to get the desired result, but atm. I am stuck
[EDIT]
I added an example object structure
Ok, I found the error. I am using Newtonsoft.Json to create the Json with this call:
string json = JsonConvert.SerializeObject(order, Format.None,
new JsonApiSerializerSettings {
NullValueHandling = NullValueHandling.Ignore
});
The part that caused the problem was the Format.None, which made the Json come out as basic Json, and not the usual format. I changed it to null, and I got the result I wanted. Big woop, wanna fight about it?

c# How do I parse a non array array

I need to parse a jsonfile that has a structure like this:
"number": {
"1": {
"branch": null,
"build": 1,
"files": [
[
"zip",
"client",
"4d96d6e8f1543c5fa1184f4771ce16e2"
],
[
"zip",
"src",
"fd397591148fac49a7d57aafdccac6a3"
],
[
"zip",
"server",
"d7e1df9a91ded33be81ee8226b027c2f"
],
[
"txt",
"changelog",
"df98aec1a868ce99532c64f246387d55"
]
],
"jobver": "1.3.2",
"mcversion": "1.1",
"modified": 1328269373.0,
"version": "1.3.2.01"
},
"2": {
"branch": null,
"build": 2,
"files": [
[
"zip",
"server",
"80fbd5d837a5867c2dd7b7967e3aa2a9"
],
[
"zip",
"client",
"0cedb5e9844e490f877b6cf04601f929"
],
[
"txt",
"changelog",
"87e9fba9322e9dbc2ea482a2c3edeec6"
],
[
"zip",
"src",
"292d5596879bd13c159a2afe571ec5eb"
]
],
"jobver": "1.3.2",
"mcversion": "1.1",
"modified": 1328613907.0,
"version": "1.3.2.2"
}
(The entire json file can be found here: http://files.minecraftforge.net/maven/net/minecraftforge/forge/json)
I have figure out the internals, in the "1" and the externals that leads to this code part, however using the Json.NET library I can't figure out how to deal with the "1" and "2"s without writing a seperate class for each. I have over 1000 of these to parse trough, so I need some way that can do it relatively simple.
My current class for parsing looks something like this:
public class forgemaven
{
public string homepage { get; set; }
public string name { get; set; }
public List<Number> number { get; set; }
public string webpath { get; set; }
}
public class Number
{
public string branch { get; set; }
public int build { get; set; }
public List<String> files { get; set; }
public string jobver { get; set; }
public string mcversion { get; set; }
public string modified { get; set; }
public string version { get; set; }
}
Note: I removed some of the things, like the first 1000 lines of version/build, since they aren't needed and json.net seems fine with that.
I have tried parsing it with http://json2csharp.com/ sadly that crashes my webbrowser. I also tried the desktop version of it, but that give me almost a MB of classes, which again isn't optimal, since new builds are constantly added to this file, so I would have to change my structure all the time, and it would be horrible to use the data from here.
So for my question: How do I do this in a maintainable way?
Your problem is that {"1" : something, "2" ; something} is not a json array, it's a json map.
In .net, you will want to deserialize that to a Dictionary<int,TObject>. Then you can process it afterwards if it really should be a `List' or an array, but you can't do that while deserializing: you got bad json in the first place, you have to deal with it.
Here is a fiddle demonstrating the thing (with the json you gave and your own classes only very slightly modified: the files property is a List<List<string>> instead of a List<String>) using Json.Net : https://dotnetfiddle.net/feqFZd
You must replace
public List<Number> number { get; set; }
with
public Dictionary<int,Number> number { get; set; }

Categories