1

I have implemented a JSON-RPC with Json.NET. The result of the response I convert with:

T data = ((JToken)value).ToObject<T>();

This work if the result is an object. But it does not work if the result is an primitive like Int64 or an string. Then the value is not a JToken.

I have found the method:

static object Convert(object initialValue, CultureInfo culture, Type targetType)

which seems to do the needed job. But the class ConvertUtils is internal. It there any public method to convert any parsed JSON result to any target type?

A more completely sample with the JSON-RPC handling:

JsonRpcResult result = serializer.Deserialize<JsonRpcResult>(jsonTextReader);
Type type = requests[result.id];
object value = result.result;
return ((JToken)value).ToObject(type);

A typical JSON string:

{"jsonrpc":"2.0","result":DynamicValidJsonDependsOnID,"id":1}

The JSON content of DynamicValidJsonDependsOnID depends on the id and can be any valid JSON. There are no limits.

The class JsonRpcResult:

[JsonObject(MemberSerialization.Fields)]
internal class JsonRpcResult
{
    private string jsonrpc;
    private object result;
    private Dictionary<String,Object> error;
    private object id;
 }
Horcrux7
  • 23,758
  • 21
  • 98
  • 156
  • what about using `Newtonsoft.Json.Linq.JObject.Parse(string json)` – Iswar Jul 17 '17 at 07:46
  • Not sure I understand your requirements. Are you looking for [`Convert.ChangeType()`](https://msdn.microsoft.com/en-us/library/ms130977(v=vs.110).aspx)? – dbc Jul 17 '17 at 07:50
  • @IswarKChettri The JSON is already parsed and I have already a JObject. But is can also an Int64 or null. See the more detailed sample. I can convert the result after it completely parsed because I need the "id" of the response first. – Horcrux7 Jul 17 '17 at 08:10
  • @dbc Yes, I search some things but it must also convert a JObject, JArray and all what the json parser can return. – Horcrux7 Jul 17 '17 at 08:11
  • @Horcrux7 - can't you just check `if (value is JToken)` and, if so, use `ToObject()`, but if not, use `Convert.ChangeType()`? – dbc Jul 17 '17 at 08:12
  • correct me if I am wrong.. that you are trying to get id from json and you are not been able to parse jsonRpc to json which is dynamic. right? – Iswar Jul 17 '17 at 08:24
  • @IswarKChettri The JSON look like: {"jsonrpc":"2.0","result":DynamicDependsOnID,"id":1} – Horcrux7 Jul 17 '17 at 08:31
  • @dbc This will be only a partial solution. The code in Json.NET for converting has multiple hundred line of code. For example string to byte[] via base64. – Horcrux7 Jul 17 '17 at 08:38
  • @Horcrux7 - in that case can you provide a [mcve] showing the JSON file(s) you want to parse and how you want to parse them? – dbc Jul 17 '17 at 08:56
  • @Horcrux7 is it possible to change your json's structure now, or you are restricted to use it as it is? – George Chondrompilas Jul 17 '17 at 11:38
  • @Horcrux7 is DynamicValidJsonDependsOnID a class? – Iswar Jul 17 '17 at 12:14

3 Answers3

2

When you deserialize your JsonRpcResult object, your object result field will either be a complex object or a primitive type.

So if it's a primitive type (ex. Int32), result.result will contain the direct value instead of a JToken

So, I would first check if the Type is primitive or not like this:

JsonRpcResult result = serializer.Deserialize<JsonRpcResult>(jsonTextReader);
Type type = requests[result.id];
object value = result.result;

if (!type.IsPrimitive && type != typeof(decimal) && type != typeof(string) && type != typeof(DateTime))
    return ((JToken)value).ToObject(type);
return value; //otherwise return the value as it is without parsing.

EDIT

As you are getting the Types on runtime, you can't cast the your objects to the correct Type as it is. You have to use the dynamic keyword as mentioned in other answers too, or check if the object's Type is the type you want and cast it like this:

if (type == typeof(string))
{
    string str = (string)returnedValue;
    ...
}
George Chondrompilas
  • 3,167
  • 27
  • 35
0

How about using Newtonsoft.Json.Jobject.Parse like this

 //==== Create class for your Json attributes
 string jsonData= " { \"Employee":{\"name\":\"John\", \"age\":31, \"city\":\"New York\" }}";
 YourJsonClass obj= new YourJsonClass();
 var jObject = Newtonsoft.Json.Linq.JObject.Parse(jsonData);
 obj= jObject["Employee"].ToObject<YourJsonClass>();

Your YourJsonClass would be

 public class YourJsonClass
 {
    public string name{ get; set; }
    public int age { get; set; }
    public string city{ get; set; }
 }

You can access through obj like this:

 string name =obj.name;
 int age=obj.age;
 string city=obj.city;

Hope it helps you.

Iswar
  • 2,211
  • 11
  • 40
  • 65
  • This is like my code. It fire an exception if YourJsonClass is an Int32, a string or any other JSON prinimtive. – Horcrux7 Jul 17 '17 at 08:15
0

You can use the keyword "dynamic" instead of hard-coded type, so it will resole the type for you. Please take a look at this tutorial:

tutorial

Stoyan Bonchev
  • 487
  • 5
  • 10
  • The problem is the converting of the parsed object. The dynamic type does not solve the class cast errors at runtime. – Horcrux7 Jul 17 '17 at 09:27