Converting a complex JSON object into a C# property - c#

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.

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.

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

Deserializing this object in JSON.NET

I have the following object:
{
"pickups": {
"7": [
5,
8
],
"10": [
6,
7,
9
],
"15": [
1
],
"20": [
0,
2
],
"25": [
3,
4
]
}
}
I'd like to de-serialize each pickups element into the following object:
public class Pickups {
public Pickup[] pickups;
}
public class Pickup {
public int Group; // This could be the 7, 10, 15, 20, 25, etc.
public int[] Values; // If this was the "7" grouping, it would contain 5, 8.
}
As you can see from the data its a bit tricky to do this. I've been trying to use a JsonConverter to convert the object with a bit of custom code but its been a nightmare and I haven't been able to get it right. I am wondering if anyone would know the best way to convert this type of object into the correct format I need?
While a converter would be a good choice you can still deserialize the Json and construct the desired object graph
var root = JsonConvert.DeserializeObject<RootObject>(json);
var pickups = new Pickups {
pickups = root.pickups.Select(kvp =>
new Pickup {
Group = int.Parse(kvp.Key),
Values = kvp.Value
}
).ToArray()
};
Where
public class RootObject {
public IDictionary<string, int[]> pickups { get; set; }
}
This is what son2csharp.com says, its gets error because you can not define names with starting number.
public class Pickups
{
public List<int> __invalid_name__7 { get; set; }
public List<int> __invalid_name__10 { get; set; }
public List<int> __invalid_name__15 { get; set; }
public List<int> __invalid_name__20 { get; set; }
public List<int> __invalid_name__25 { get; set; }
}
public class RootObject
{
public Pickups pickups { get; set; }
}
But I think
[DataMember(Name = "Name")]
should work cause its not an error in JSON format side.
If it is a viable option for you to use JObject.Parse(...) instead, you could use the following code (and write it more cleanly, with exception handling and safe casts and so on):
var jsonPickups = JObject.Parse(json);
var myPickups = new Pickups
{
pickups = jsonPickups.First.First.Select(x =>
{
JProperty xProp = x as JProperty;
return new Pickup
{
Group = int.Parse(xProp.Name),
Values = (xProp.Value as JArray).Select(y => int.Parse(y.ToString())).ToArray()
};
}).ToArray()
};

Parsing json with an odd format

Note: Please post in comments if you have a better title for this post. Thanks!
I am working with an api that returns json that looks like the snippet below. I am pretty familiar with json but I have never seen a structure that looks like this.
The resultFieldList fieldNames are fixed (4 below but there are about 20). The values array is variable, but the same length for each fieldName.
I am thinking that I should count a non-null field (OrderNumber) and then iterate through each fieldName, but that seems inefficient. I am wondering if there is a better way. This is how I am getting the record count:
string result = await response.Content.ReadAsStringAsync();
JObject m_json = (JObject)JsonConvert.DeserializeObject(result);
int m_count = m_json["resultFieldList"][3]["values"].Count();
This is the json snippet.
{
"collectionName": "Transactions",
"recordCount": 0,
"skippedRecordCount": 0,
"resultFieldList":
[{
"fieldName": "SaleChannel",
"analyticsDataType": "STRING",
"values": ["Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online"]
},
{
"fieldName": "Quantity",
"analyticsDataType": "INTEGER",
"values": [1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1, 3]
},
{
"fieldName": "Amount",
"analyticsDataType": "CURRENCY",
"values": ["25.00", "14.00", "14.00", "50.00", "14.00", "50.00", "14.00", "25.00", "18.00", "50.00", "36.00", "25.00", "50.00", "25.00", "14.00", "25.00", "50.00", "50.00", "25.00", "75.00"]
},
{
"fieldName": "OrderNumber",
"analyticsDataType": "STRING",
"values": ["60937129", "60937129", "53221966", "14599547", "14599547", "10478305", "10478305", "95344699", "95344699", "83413371", "65720270", "43458148", "52500933", "32742144", "32742144", "89850688", "61514108", "11080559", "90497730", "22838522"]
}]
}
The precise question is is it possible to create a new array or object where the index of each value is combined into a new object given this structure. For example, the values of index[0] are "Online",1,"25.00","60937129". So it may be a new array or a whole new json object. If so, how would I create either one or the other? The output would be something like this:
[ { "Online",1,"25.00","60937129" },{...} ]
Or
{"results": [ { "SaleChannel": "Online" , "Quantity": 1, "Amount": "25.00", "OrderNumber": "60937129" } , {...} ]
ANSWER
Using #JLRishe's answer I am able to parse and use the data for the use case - inserting api data into a data warehouse.
Edit: I believe I have addressed the main point of your question toward the end of my answer.
You're probably best off defining a type to represent this structure. Since the contents of the values arrays have varying types, you can't really make an assumption about them and would probably be safest treating them as objects:
public class MyClass
{
public string collectionName { get; set; }
public int recordCount { get; set; }
public int skippedRecordCount { get; set; }
public ResultField[] resultFieldList { get; set; }
}
public class ResultField
{
public string fieldName { get; set; }
public string analyticsDataType { get; set; }
public object[] values { get; set; }
}
Then parsing the JSON is simply a matter of:
string result = await response.Content.ReadAsStringAsync();
MyClass obj = JsonConvert.DeserializeObject<MyClass>(result);
When actually using the data, you would need to look at the value in analyticsDataType for each respective ResultField and cast the contents of the values properties accordingly.
Alternatively, if you don't care that much about treating the values as their original types, you could treat them all as strings, which would require less type checking. Everything else would remain the same:
public string[] values { get; set; }
Edit: Now that you've clarified the question a bit more, it seems this is mostly about arranging the data into a more nicely consumable fashion.
If there isn't anything outside the resultFieldList that indicates the number of values in each value array, then you would basically need to arbitrarily pick one to get the count:
int valueCount = obj.resultFieldList[0].values.Length;
Then once you have that, you could assemble the values together:
// assuming OrderItem is a class you've defined with the needed
// properties for one entry in an order
IEnumerable<OrderItem> items = Enumerable
.Range(0, valueCount)
.Select(i => new OrderItem {
SaleChannel = Convert.ToString(obj.resultFieldList[0].values[i]),
Quantity = Convert.ToInt32(obj.resultFieldList[1].values[i]),
Amount = Convert.ToDecimal(obj.resultFieldList[2].values[i]),
// etc...
});
Use Newtonsoft.Json and do something like this:
Define your classes:
public class SomeObject
{
public List<DynamicProperty> resultFieldList { get; set; }
}
public class DynamicProperty
{
public string fieldName { get; set; }
public string analyticsDataType { get; set; }
public List<object> values { get; set; }
}
Deserialize your JSON:
var obj = JsonConvert.DeserializeObject<SomeObject>(json);
var t = obj.resultFieldList[3].values.Count();
Please let me know if you have any questions. I tested using your JSON and the answer was 20. Additionally, you could use Linq to do more complex analysis.
Edited: Based on question being expanded.
Create an Order class:
public class Order
{
public string SaleChannel { get; set; }
public int Quantity { get; set; }
public Decimal Amount { get; set; }
public string OrderNumber { get; set; }
}
Generate the json enumerable based and serialize:
var jsonValue = JsonConvert.SerializeObject(Enumerable
.Range(0, obj.resultFieldList.Max(x => x.values.Count))
.Select(i => new Order()
{
SaleChannel = obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.SaleChannel))?.values[i].ToString(),
Quantity = Convert.ToInt32(obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.Quantity))?.values[i].ToString()),
Amount = Convert.ToDecimal(obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.Amount))?.values[i].ToString()),
OrderNumber = obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.OrderNumber))?.values[i].ToString()
}));

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

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

Categories