How to populate an object properties with a constructor using JSON in C#?

-1

I asked earlier today, but still struggling with this. I want to create an object Person where the properties must be populated from an RPC call when instantiated.

I get this error:

Newtonsoft.Json.JsonReaderException
  HResult=0x80131500
  Message=Could not convert string to integer: getperson. Path 'id', line 1, position 103.
  Source=Newtonsoft.Json

My example is below, I tried changing Id property to a string in the Person object but then the none of the properties don't get set (null or zero).

I've also heard it mentioned that I should use a static factory method. What's that and how would it look in this example? Many thanks.

using Newtonsoft.Json;

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Version { get; set; }

    public Person(int Id)
    {
        // here would be an RPC call to get the FirstName,LastName,Version. result is JSON    
        string response = "{\"result\": {\"version\":1,\"Id\": 1, \"FirstName\": \"Bob\", \"LastName\": \"Jones\"},\"error\":null,\"id\":\"getperson\"}";
        JsonConvert.PopulateObject(response, this);
    }
}
class Program
{
    static void Main(string[] args)
    {
        var p = new Person(1);
        var f = p.FirstName;
        // p.FirstName should be Bob but is null
    }
}

EDIT: In my actual code I have another class like this, can I make use of that and somehow derserialize with RPCResponse<Person>?

public class RPCResponse<T>
{
    public T result { get; set; }
    public string error { get; set; }
    public string id { get; set; }
}
c#
json
asked on Stack Overflow Jan 6, 2019 by Mark Allison • edited Jan 6, 2019 by Mark Allison

4 Answers

1

Based on the current example, the constructor is taking on too many responsibilities.

You mentioned using a factory method. Go with that.

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Version { get; set; }

    public Person()    { 
    }

    public static Person Get(int id) {
        // here would be an RPC call to get the FirstName,LastName,Version. result is JSON

        string json = "{\"result\": {\"version\":1,\"Id\": 1, \"FirstName\": \"Bob\", \"LastName\": \"Jones\"},\"error\":null,\"id\":\"getperson\"}";

        dynamic jObject = JObject.Parse(json);  

        var person = jObject.result.ToObject<Person>();

        return person;
    }
}

The static Get(int Id) factory method would be responsible for parsing the response from the service. That could have also been refactored out into a service, but the main point here is that the constructor should be kept as simple as needed.

public class Program
{
    public static void Main(string[] args)
    {
        var p = Person.Get(1);

        var f = p.FirstName;
        var l = p.LastName;

        Console.WriteLine("FirstName: "+ f);
        Console.WriteLine("LastName: "+ l);
    }
}

//Produces:
//  FirstName: Bob
//  LastName: Jones

.Net Fiddle of above code

answered on Stack Overflow Jan 6, 2019 by Nkosi
0

the class you are trying to populate is in the inner properties of your json string. try to create a class like this

public class Response{
  public Response(
    string response = "{\"result\": {\"version\":1,\"Id\": 1, \"FirstName\": \"Bob\", \"LastName\": \"Jones\"},\"error\":null,\"id\":\"getperson\"}";
    JsonConvert.PopulateObject(response, this);
  ){}
  public Person result{get;set;}

}
public class Person{
  public Person(){}
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public int Version { get; set; }
}

this is a non tested code, but i hope you will get the idea.

answered on Stack Overflow Jan 6, 2019 by Vilsad P P
0

I have solved it like this, but I don't like my code. How could it be improved? It seems very verbose.

using Newtonsoft.Json;

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Version { get; set; }

    public Person(int Id)
    {
        // here would be an RPC call to get the FirstName,LastName,Version. result is JSON    
        string response = "{\"result\": {\"version\":1,\"Id\": 1, \"FirstName\": \"Bob\", \"LastName\": \"Jones\"},\"error\":null,\"id\":\"getperson\"}";             
        var o = JsonConvert.DeserializeObject<RPCResponse<PersonDetails>>(response).result;
        this.Id = Id;
        FirstName = o.FirstName;
        LastName = o.LastName;
        Version = o.Version;
    }

    private class PersonDetails
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Version { get; set; }
    }
}

public class RPCResponse<T>
{
    public T result { get; set; }
    public string error { get; set; }
    public string id { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        var p = new Person(1);
        var f = p.FirstName;
        // p.FirstName should be Bob but is null
    }
}
answered on Stack Overflow Jan 6, 2019 by Mark Allison • edited Jan 6, 2019 by Mark Allison
0

Not sure what the problem is with your code but this code maps the JSON directly into a class of PersonDetails and it's properties correctly: using System; using Newtonsoft.Json;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = "{\"result\": {\"version\":1,\"Id\": 1, \"FirstName\": \"Bob\", \"LastName\": \"Jones\"},\"error\":null,\"id\":\"getperson\"}";
            var personDetails = new PersonDetails(json);

            Console.WriteLine(personDetails.ToString());        
            Console.ReadLine();
        }
    }

    public class RPCResponse<T>
    {
        public T Result { get; set; }
        public string Error { get; set; }
        public string Id { get; set; }
    }

    public class PersonDetails
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Version { get; set; }

        public PersonDetails() {}

        public PersonDetails(string json)
        {
            var result = JsonConvert.DeserializeObject<RPCResponse<PersonDetails>>(json).Result;

            foreach (var prop in typeof(PersonDetails).GetProperties())
            {
                var value = prop.GetValue(result);
                prop.SetValue(this, value);
            }
        }

        public override string ToString()
        {
            var str = "Id: " + this.Id + Environment.NewLine;
            str += "FirstName: " + this.FirstName + Environment.NewLine;
            str += "LastName: " + this.LastName + Environment.NewLine;
            str += "Version: " + this.Version + Environment.NewLine;
            return str;
        }
    }
}
answered on Stack Overflow Jan 6, 2019 by Westerlund.io • edited Jan 6, 2019 by Westerlund.io

User contributions licensed under CC BY-SA 3.0