This question already has answers here:
Using Json.NET converters to deserialize properties
(9 answers)
Closed 6 years ago.
Is there a way to serialize and then deserialize a class that has a member variable of unknown type that could be either be a simple value type or an instance of the containing class itself ?
public class A
{
public dynamic Value { get; set; }//Value could be int or type A for example
}
public static class ASerializer
{
public static string ToJson(A table)
{
return JsonConvert.SerializeObject(table);//using Json.Net
}
public static A FromJson(string json)
{
return JsonConvert.DeserializeObject<A>(json);
}
}
public class Tests
{
public static void TestASerialization()
{
var a = new A() { Value = 1 };
var aa = new A { Value = a };
var aaa = new A { Value = aa };
var json = ASerializer.ToJson(aaa);
var aaa2 = ASerializer.FromJson(json);
var aa2 = (A)aaa2.Value; //throws
}
}
if I serialize and then deserialize aaa - I can't cast the Value of the deserialized aaa back to type A I get:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot convert type 'Newtonsoft.Json.Linq.JObject' to
'A'
Any suggestions on handling this nested hierarchy elegantly, without resorting to hand coding ?
Seems to work with just one instance of A with Value of type A.
You aren't casting what you think you're casting.
In this case, you're actually casting the Value property to A. You need to wrap the aaa2 instance in params with the cast before accessing the property.
var aa2 = ((A)aaa2).Value;
Dynamic is a compiler hack mostly, I would recommend generics instead.
#David L 's answer is also correct.
public class A<T>
{
public T Value { get; set; }
}
Related
This question already has answers here:
Deserialize collection of interface-instances?
(9 answers)
Closed 3 years ago.
I have multiple classes extended from an interface and I have a json editor to edit each of those classes that I have in a List, "I" being my interface
So let's say I have the variable of the current class which properties have been edited
I now have the new Json that contains the new values
How do I deserialize the new json according to the current class being edited?
I have access to the class name if that can help but I can't find a way to do
I have tried .GetType() for the current selected Class : IRule and reflector
class RuleOne : IRule
{
public bool variable{ get; set; }
public int num;
}
class RuleTwo : IRule
{
public bool variable{ get; set; }
public string name;
}
List<IRule> Rules = new List<IRule>;
Rules.Add(new RuleOne());
Rules.Add(new RuleTwo());
string json = JsonConvert.SerializeObject(Rules[0]);
// How do I deserialize the json string into Rules[0] ?
I expect the modified json to be stored in it's original class
You need to help serializer to remember the types.
Check this thread for more details.
Type type = Type.GetType($"{EditorRule.GetType().Namespace}.{EditorRule.GetType().Name}"); // Can be replaced dynamically
EditorRule = (IRule)JsonConvert.DeserializeObject(JsonText, type);
This worked for me, I didn't know you could also pass a "dynamic" type as an argument to JsonConvert.Deserialize()
I have a c# class that allows you to specify a generic type. I would like to be able to reuse this class to remove the noise of a json wrapper that all objects will share, a value property that holds the data I need.
If the reusable class has a property of value that gets me the first step of the way. But I'm having trouble deserializing into the generic type supplied, because when I cast it always returns null. I know this is because the actual type of value after deserialization is probably JObject or similiar, I forget the type exactly. You can see in my demo app that it does indeed grab all of the data, but I can't just cast it into my generic type, because it isn't actually that type yet.
var get1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }");
var name1 = get1.Get();//name1 is null
var getList1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: [{...}] }");
var nameList = getList1.List();//nameList is null
public class BaseResponse<T> where T : BaseObj
{
public object value;
public T Get()
{
return value as T;
}
public List<T> List()
{
return value as List<T>;
}
}
public class NameObj : BaseObj
{
public string Name { get; set; }
}
I'll have more than one type of BaseObj class.
So, I'm wondering what is better:
manipulate json first to grab value out, and deserialize that
fix how I'm deserializing the BaseReponse<T> to better get at the generic inside the value property
I suppose solution 1 will do for now, since all of the json follows that pattern, but I was hoping for a pure deserialize instead of having to do string manipulation.
repo here: https://github.com/nateous/JSONDeserializeBaseWithGeneric
Your problem is that, while BaseResponse<T> is typed, the underlying data member public object value is untyped, and thus Json.NET has no idea of how to deserialize it. What it does in practice is to deserialize to some type that is sufficient to capture the JSON to be deserialized, typically some JToken hierarchy.
Since you don't want this, you should make the property typed, e.g. like so:
public abstract class BaseResponseBase
{
// Allows for non-generic access to the BaseResponse value if needed
// Use a method rather than a property to prevent accidental serialization.
public abstract object GetBaseValue();
}
public class BaseResponse<T> : BaseResponseBase
{
public override object GetBaseValue() { return Value; }
public T Value { get; set; }
}
Since the value does not always inherit from BaseObj (specifically, when it is a list and not an object) the generic constraint is no longer appropriate. BaseResponseBase provides non-generic access to the deserialized value. If such access is never needed, the base class can be omitted.
And then to deserialize, do:
var name = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }").Value;
var nameList = JsonConvert.DeserializeObject<BaseResponse<List<NameObj>>>("{ value: [{...}] }").Value;
Incidentally, you could always just use JsonConvert.DeserializeAnonymousType instead to peel off the outer container object:
var name = JsonConvert.DeserializeAnonymousType("{ value: {...} }",
new { value = (NameObj)null })
.value;
This is strictly preferable to using string manipulation to deserialize JSON.
To solve this:
var get1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }");
var name1 = get1.Get();//name1 is null
Change the type of value in BaseResponse class from object to T.
public class BaseResponse<T> where T : BaseObj
{
public T value; //from object to T
public T Get()
{
return value as T;
}
public List<T> List()
{
return value as List<T>;
}
}
Now for this:
var getList1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: [{...}] }");
var nameList = getList1.List();//nameList is null
Deserializing ListBaseJSON returns a BaseObj array but BaseResponse class has a constraint of BaseObj. You may have to remove the constraint.
So your BaseResponse class becomes:
public class BaseResponse<T>
{
public T value;
public T Get()
{
return value;
}
}
So, now you can:
var get1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }");
var name1 = get1.Get();//name1 is null
var getList1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: [{...}] }");
var nameList = getList1.List();//nameList is null
I have a dynamic object in C# that I'd like to convert to a static object. I wrote a function that takes the dynamic type and returns the static type, but it actually returns dynamic, ignoring the specified return type. (This is standard behavior, as I've now discovered.) AutoMapper doesn't handle dynamic types. How can I properly convert dynamic to static?
Using some serializers can be a solution. Suppose you form a dynamic object like
dynamic d = new ExpandoObject();
d.a = 1;
d.b = new ExpandoObject();
d.b.c = "222";
and you want to cast this to A
public class A
{
public int a { set; get; }
public B b { set; get; }
}
public class B
{
public string c { set; get; }
}
You can use, for example, Json.Net, to do this serialization/deserialization
A a = JsonConvert.DeserializeObject<A>(JsonConvert.SerializeObject(d));
If you got the type, you can instanciate a new object, then copy the state of your dynamic object into this object with the FormatterServices class:
var staticObject = Activator.CreateInstance(yourType);
MemberInfo[] members = FormatterServices.GetSerializableMembers(yourType);
FormatterServices.PopulateObjectMembers(staticObject, members,
FormatterServices.GetObjectData(dynObject, members));
I'm confused... I thought that .NET should already do this for you. Here's some test code and it fits with my expectations:
class Program
{
static void Main(string[] args)
{
dynamic anythingGoes = 1;
var convertedToInt = ConvertToType<int>(anythingGoes);
// expectation: should output Int32. and it does....
Console.WriteLine(convertedToInt.GetType().Name);
anythingGoes = "ribbit";
var convertedToString = ConvertToType<string>(anythingGoes);
// expectation: should output String. and it does also...
Console.WriteLine(convertedToString.GetType().Name);
Console.ReadLine();
}
// just a small method to cast the dynamic to whatever i want
// ...only for this test. not guaranteed to be crash safe. in fact, don't assume!
static T ConvertToType<T>(dynamic obj)
{
T result = obj;
return result;
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I read the properties of a C# class dynamically?
I have to get values of class members using strings of their names only. I think I have to use Reflection but I am not realy sure how to. Can you help me?
MemberInfo member = typeof(MyClass).GetMember("membername");
GetMember reference.
If you know type of member you're looking for, you can use .GetMethod, .GetField, .GetProperty, etc.
If you don't know the type you are working with:
var myobject = someobject;
string membername = "somemember";
MemberInfo member = myobject.GetType().GetMember(membername);
Different member types have different means to getting the value. For a property you would do:
var myobject = someobject;
string propertyname = "somemember";
PropertyInfo property = myobject.GetType().GetProperty(membername);
object value = property.GetValue(myobject, null);
public class Foo
{
public string A { get; set; }
}
public class Example
{
public void GetPropertyValueExample()
{
Foo f = new Foo();
f.A = "Example";
var val = f.GetType().GetProperty("A").GetValue(f, null);
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using Json.net - partial custom serialization of a c# object
I have a class that I successfully get to serialize in json.net when using asp.net MVC 4 WebAPI. The class has a property that is a list of strings.
public class FruitBasket {
[DataMember]
public List<string> FruitList { get; set; }
public int FruitCount {
get {
return FruitList.Count();
}
}
}
In my Get method the serialization happens ok and I get an empty array i.e. [] for the FruitList property in my JSON. If I use the same json in a PUT request's body I get an error in the FruitCount property during deserialization because FruitList is null.
I want the FruitList property (basically my get only properties) to serialize but not deserialize. Is it possible with a setting or other wise with json.net?
I realize this does not answer your question, but addresses the error being generated so might make worrying about custom serialization irrelevant
use a private variable for FruitList, return it in the get and in set, if value is null then set the private variable equal to a new list.
public class FruitBasket
{
private List<string> _fruitList;
[DataMember]
public List<string> FruitList
{
get
{
return _fruitList;
}
set
{
if (value == null)
{
_fruitList = new List<string>();
}
else
{
_fruitList = value;
}
}
}
public int FruitCount
{
get
{
return FruitList.Count();
}
}
}