Automapper and use a alternative key - c#

How can I map two objects like
class Parent
{
public Guid Id { get; set; }
public IEnumerable<Child> Childrens { get; set; }
}
class Child
{
public Guid Id { get; set; }
public int AlternativeKey { get; set; }
}
Parent1
{
"Id": "1367debe-7d88-41c7-b152-0ff0747e5d4b",
"Children": [{
"Id":"8d1377b7-1190-48b1-aa21-53a2eb95837b",
"AlternativeKey":"13",
"Name":""
},
{
"Id":"ed3eea42-4ff3-40f0-9b84-7f8c4ae6f603",
"AlternativeKey":"14",
"Name":""
}
]
}
Parent2
{
"Id": "00000000-0000-0000-0000-000000000000",
"Children": [{
"Id":"00000000-0000-0000-0000-000000000000",
"AlternativeKey":"13",
"Name":"ABC"
},
{
"Id":"00000000-0000-0000-0000-000000000000",
"AlternativeKey":"14",
"Name":"Foo"
}
]
}
And now I want to merge these with automapper. And the result should be the name from Parent2 in Parent1. My problem is to use AlternativeKey as mapping primary key instead of Id.
Expected result
{
"Id": "1367debe-7d88-41c7-b152-0ff0747e5d4b",
"Children": [{
"Id":"8d1377b7-1190-48b1-aa21-53a2eb95837b",
"AlternativeKey":"13",
"Name":"ABC"
},
{
"Id":"ed3eea42-4ff3-40f0-9b84-7f8c4ae6f603",
"AlternativeKey":"14",
"Name":"Foo"
}
]
}

Related

Add item to JSON array section in C#

{
"name": "Not Okay Bears Solana #1",
"image": "ipfs://QmV7QPwmfc6iFXw2anb9oPZbkFR75zrtw6exd8LherHgvU/1.png",
"attributes": [
{
"trait_type": "Background",
"value": "Amethyst"
},
{
"trait_type": "Fur",
"value": "Warm Ivory"
},
{
"trait_type": "Mouth",
"value": "Clean Smile"
},
{
"trait_type": "Eyes",
"value": "Not Okay"
},
{
"trait_type": "Hat",
"value": "Bucket Hat"
},
{
"trait_type": "Clothes",
"value": "Plaid Jacket"
},
{
"trait_type": "Eyewear",
"value": "Plastic Glasses"
}
],
"description": "Not Okay Bears Solana is an NFT project for mental health awareness. 10k collection on the Polygon blockchain. We are not okay."
}
I need to add an object to attributes.
How to do this?
My JSON classes:
public class Attribute
{
public string trait_type { get; set; }
public string value { get; set; }
}
public class Root
{
public string name { get; set; }
public string image { get; set; }
public List<Attribute> attributes { get; set; }
public string description { get; set; }
}
try this, in this case you don't need any classes
var jsonObject = JObject.Parse(json);
JObject obj = new JObject();
obj.Add("trait_type", "type");
obj.Add("value", "value");
((JArray)jsonObject["attributes"]).Add(obj);
var newJson=jsonObject.ToString();
but if you need the data not a json , you can use this code
Root data = JsonConvert.DeserializeObject<Root>(json);
data.attributes.Add(new Attribute { trait_type="type", value="value"});

c# Json retrieve a specific node with his level

I've created two c# classes and then deserialize the Json returned to work with it natively.
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
The Data returned is like this
[
{
"children": [
{
"children": [
{
"children": [
{
"children": [],
"myentity": "ENT2_A",
"from": "2019-10-01",
"structureId": 34353,
"to": null
},
{
"children": [
{
"children": [],
"myentity": "ENT3_A",
"from": "2019-10-01",
"structureId": 34349,
"to": null
},
{
"children": [],
"myentity": "ENT3_B",
"from": "2019-10-01",
"structureId": 34351,
"to": null
}
],
"myentity": "ENT2_B",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT1_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT0_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
]
}
]
I need to get all "myentity" elements and if it's possible in which level resides.
If not possible obtain level, another way is get all "myentity" for each level.
Probably there are much better and elegant ways of doing this. This is without thinking on it much:
void Main()
{
var st = JsonConvert.DeserializeObject<List<structureTree>>(myjson);
List<Tuple<string,int>> entities = new List<System.Tuple<string, int>>();
foreach (var stc in st)
{
foreach (var sc in stc.children)
{
GetMyEntity(entities, sc, 0);
}
}
foreach (var e in entities)
{
Console.WriteLine($"{e.Item1}, {e.Item2}");
}
}
void GetMyEntity(List<Tuple<string,int>> entities, structureChildren c, int level)
{
entities.Add(Tuple.Create(c.myentity,level));
level++;
foreach (var sc in c.children)
{
GetMyEntity(entities, sc, level);
}
}
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
static readonly string myjson = #"[
{
""children"": [
{
""children"": [
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_A"",
""from"": ""2019-10-01"",
""structureId"": 34353,
""to"": null
},
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_B"",
""from"": ""2019-10-01"",
""structureId"": 34349,
""to"": null
},
{
""children"": [],
""myentity"": ""ENT3_C"",
""from"": ""2019-10-01"",
""structureId"": 34351,
""to"": null
}
],
""myentity"": ""ENT2_A"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
],
""myentity"": ""ENT1_1"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
]
}
]
}
]";
Output:
, 0
ENT1_1, 1
ENT3_A, 2
ENT2_A, 2
ENT3_B, 3
ENT3_C, 3
You can do it in two ways, with a stack/queue or recursion. I personally prefer stacks since recursion is hard(er) to debug. This is a quick draft. I'm sure someone else can give you a fancy recursion version with Linq, but I think this illustrates the steps you need to take better.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var structure = new StructureTree();
var currentStack = new Stack<StructureChildren>(structure.children);
var nextStack = new Stack<StructureChildren>();
var flatStructure = new List<KeyValuePair<int, string>>();
int currentLevel = 0;
bool loop = true;
while (loop)
{
var currentItem = currentStack.Pop();
foreach (var child in currentItem.children)
nextStack.Push(child);
flatStructure.Add(new KeyValuePair<int, string>(currentLevel, currentItem.myentity));
if (currentStack.Count == 0)
{
if (nextStack.Count == 0)
break;
currentLevel++;
currentStack = new Stack<StructureChildren>(nextStack);
nextStack.Clear();
}
}
}
public class StructureTree
{
public StructureChildren[] children { get; set; }
}
public class StructureChildren
{
public StructureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
}
PS: Please look into the naming convention provided by Microsoft. Class names should be CapitalizedAtEveryWord and property names too. Your current naming scheme is typically used for Java, not C#.

Change value in json, when other value is looking for

I have Json where i have 2 objects. I would like to know how to change value in my json, when other value is looking for. For example i would like to change "speciality" to "Warrior" for Person who's "Name" is Harry.
It's my Json
{
"Person": [
{
"Speciality": "Archer",
"Id": 432742,
"Name": "Charlie",
"Surname": "Evans",
"Items": [
"Bow",
"Arrow",
]
},
{
"Speciality": "Soldier",
"Id": 432534,
"Name": "Harry",
"Surname": "Thomas",
"Items": [
"Gun",
"Knife",
]
}
],
"Monster": [
{
"Name": "Papua",
"Skills": [
"Jump",
"SlowWalk",
]
},
{
"Name": "Geot",
"Skills": [
"Run",
"Push",
]
}
]
}
My classes
public class Person
{
public string Speciality { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public List<string> Items { get; set; }
}
public class Monster
{
public string Name { get; set; }
public List<string> Skills { get; set; }
}
public class Root
{
public List<Person> People { get; set; }
public List<Monster> Monsters { get; set; }
}
I tried something like this:
var result = JsonSerializer.Deserialize<Root>(jsonfile)
for (int i = 0; i < result.People.Count; ++i)
{
result.Where(w => w.Person.Name == "Harry").ToList().ForEach(s => s.Person.Speciality = "Warrior");
}
Thanks in advance for some help.
Your can use foreach loop
var result = JsonSerializer.Deserialize<Root>(jsonfile);
foreach (var person in result.Person)
{
if(person.Name == "Harry"){
person.Speciality = "";
}
}

Deserialize from minimal JSON to hierachical objects with mandatory back-references

Assume those hierachical object structure: Tree➻Branch➻Leaf
public class Tree
{
public string Name { get; set; }
public List<Branch> Nodes { get; set; } = new List<Branch>();
}
public class Branch
{
public Branch(Tree parent) { Parent = parent; }
public Tree Parent { get; }
public string Name { get; set; }
public List<Leaf> Nodes { get; set; } = new List<Leaf>();
}
public class Leaf
{
public Leaf(Branch parent) { Parent = parent; }
public Branch Parent { get; }
public string Name { get; set; }
}
A not so simple serialization output would be (using ReferenceLoopHandling.Serialize AND PreserveReferencesHandling = PreserveReferencesHandling.Objects):
{
"$id": "1",
"Name": "AnOakTree",
"Nodes": [
{
"$id": "2",
"Parent": {
"$ref": "1"
},
"Name": "TheLowestBranch",
"Nodes": [
{
"$id": "3",
"Parent": {
"$ref": "2"
},
"Name": "OneOfAMillionLeaf"
}
]
}
]
}
Deserialization works perfectly, nothing to complain! But I'd like to omit reference handling at all to reduce JSON footprint and improve readability.
What's the best way to deserialize JSON without reference informations and invoke the constructors with the correct parameter (the instance of the parent node)? So that the back-references will be recreated by code?

Pick out specific, optional key from metavalues object in JSON and store into my class

I'm struggling to make this conversion happen, and not sure it's entirely feasible. My JSON from a third party could look like this:
{
"equipments": [
{
"serialNumber": "11-17-053",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787596"
},
{
"serialNumber": "11-17-054",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787597"
},
{
"serialNumber": "8-17-022",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1505326964589,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59b9777480e426009d01d48d"
},
{
"serialNumber": "22A-17-001",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1504908025733,
"fieldOffice_id": "58b74b080c206710004ff726",
"clients_id": [
"59bbfdf5725cd00012fb15d8"
],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33122
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
},
"g99idmcqyuo2na9e6l": "YARD",
"709pm94prt2tpjt90y": 5,
"bgen1h4i5b6f8xa1kh": "9/8/2017 7:18:24 PM",
"yvtvsl8dedudqjtdud": "0.00000, 0.00000",
"aj3h2b5fdbic9s72m3": "Parex",
"8wt1re82xidjiv8rzi": "YARD"
},
"schedules": [],
"id": "59b312f93256d5009c4a73fb"
},....
This is obviously not a complete example, but should help get my question across.
Is there a way to create a C# class that pulls in certain fields only if they exist from the "metavalues" array?
My current class is as follows which works to get the data, but not exactly how I want.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("metavalues")]
public Dictionary<string, object> metavalues { get; set; }
}
What I'm after, is taking the key of "g99idmcqyuo2na9e6l" which is optional in the metavalues, and store it in a property called "LeaseName".
I tried the following to no avail.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
If I try to make a class for the metavalues section, I get an exception indicating that JSON.NET can't convert it to my object, hence why I used the Dictionary<string, object> option.
EDIT # 1: The accepted answer works for me, but for those who stumble upon this and truly need a property name from a nested array you could try the following.
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (metavalues != null)
{
if (metavalues.ContainsKey("g99idmcqyuo2na9e6l"))
{
string _LeaseName = (string)metavalues["g99idmcqyuo2na9e6l"];
LeaseName = _LeaseName;
}
}
}
I think my edit approach is a bit overkill but just throwing this out there.
Yes, this is possible, but since the lease value is still one level down in the JSON you need an intermediate class to hold it (to replace the dictionary).
public class Equipment
{
...
[JsonProperty("metavalues")]
public MetaValues MetaValues { get; set; }
}
public class MetaValues
{
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
Fiddle: https://dotnetfiddle.net/Ddqzc7

Categories

Resources