batuzai04123
batuzai04123

Reputation: 389

Alternative way to read json with Newtonsoft.json-mapped to C#.net models

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

Answers (3)

er-sho
er-sho

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:

enter image description here

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

zetawars
zetawars

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

Akshay Raut
Akshay Raut

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

Related Questions