Reputation: 389
Apologies for not giving the best/appropriate title for my thread, If you have a better title than me, will be glad to update it.
My current issue is that I have to work on an existing code that uses Newtonsoft.JSON that reads json from .JSON file(provided from 3rd party source). It is mapped to an existing class as well. Im not sure if this is the right way by doing IF-ELSE just to get to the proper json node, maybe someone would have their other options/better approach than mine. Thank you.
This is not the exact code, but I replicated it related to my issue.
PET.JSON File:(JSON File is provided by 3rd party, structure/schema is same like the example below, and it is their format ever since-no permission to change JSON format)
{
"Pet": {
"Dog": {
"cute": true,
"feet": 4
},
"Bird": {
"cute": false,
"feet": 2
}
}
}
The Pet Class & subclasses (this is 3rd party standard structure, i dont have permission to modify it)
public class Pet
{
public Dog dog { get; set; }
public Bird bird { get; set; }
public class Dog {
public bool cute { get; set; }
public int feet { get; set; }
}
public class Bird
{
public bool cute { get; set; }
public int feet { get; set; }
}
}
The Pet Reader (I am required to use this Deserialized Json Object mapped to the models above, don't have permission to modify their implementation 'yet' I'll have to manage myself on how to use the return value of ReadPetJSON())
public static Pet ReadPetJSON()
{
string JSON_TEXT = File.ReadAllText("PET.JSON");
Pet pet = Newtonsoft.Json.JsonConvert.DeserializeObject<Pet>(JSON_TEXT);
return pet;
}
Update: I found out about using Reflection, and I can pass a variable name to find the PropertyName. Thank you all for your help and inputs, I appreciated it
http://mcgivery.com/c-reflection-get-property-value-of-nested-classes/
// Using Reflection
Pet pet = ReadPetJSON();
// Search Bird > feet using 'DOT' delimiter
string searchBy = "bird.feet"
foreach (String part in searchBy.Split('.'))
{
if (pet == null) { return null; }
Type type = pet.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; } // or make a catch for NullException
pet = info.GetValue(pet, null);
}
var result = pet.ToString(); // Object result in string
Console.WriteLine("Bird-Feet: {0}", result);
Output:
Bird-Feet: 2
Upvotes: 1
Views: 1283
Reputation: 9771
I'm thinking like this, but I know it's not possible.
Yes, yes its possible by below code.
You have to Querying
your json like
string JSON_TEXT = File.ReadAllText("PET.JSON");
JObject jObject = JObject.Parse(JSON_TEXT);
//This is your search term
string search = "Dog"; //or "Bird", or "Lion", or "Tiger", or "Eagle" or anything that are present it your json
bool cute = (bool)jObject["Pet"][search]["cute"];
int feet = (int)jObject["Pet"][search]["feet"];
string temp = $"My {search} is cute = {cute} and feet = {feet} ";
//If you want it in your strongly type then
Dog dog = jObject["Pet"][search].ToObject<Dog>();
Bird bird = jObject["Pet"][search].ToObject<Bird>();
Output:
In above code
["Pet"] => 0 st position level node of your json.
[search] => 1 st position level node of your json.
["cute"] or ["feet"] => 2 nd position level node of your json and many more as your json depth
You can find more about Querying Json
here
Upvotes: 0
Reputation: 1071
Well, you can try these classes instead, then loop on the Pet list.
public class JsonParsed
{
public Dictionary<string, Attribute> Pet { get; set; }
}
public class Attribute
{
public bool cute { get; set; }
public int feet { get; set; }
}
The key contains the name of the pet, and the Attribute will contain the other properties.
var json = @"{'Pet': {'Dog': {'cute': true,'feet': 4},'Bird': {'cute':
false,'feet': 2}}}";
var obj = JsonConvert.DeserializeObject<JsonParsed>(json);
foreach (var element in obj.Pet)
{
Console.WriteLine(element.Key + " has " + element.Value.feet);
}
Upvotes: 2
Reputation: 413
This type of structure with same properties is not easy to maintain according to OOP and other design principles. If you can change the classes and JSON structure then I would recommend following sample structure.
[{
cute : true,
feet : 4,
type : "dog"
}, {
cute : true,
feet : 2,
type : "bird"
}]
And instead of a class with Bird and Dog child classes, we can have an List of Pet class objects.
class Pet
{
int Feet {get; set; }
string Type { get; set; }
bool Cute { get; set; }
}
now in your method where you expect to read it, you can read Json and return the list to be searched.
List<Pet> pets = ReadPetJson();
string Pet_Name = DummyPetName(); // Returns string 'Bird' or 'Dog' etc.
var matchedPet = pets.FirstOrDefault(x =>
x.Type.ToLower() == Pet_Name);
if (matchedPet != null)
return matchedPet.Cute;
Upvotes: 0