How to remove a child from System.Object object? - c#

At a Rest-API I got an incoming object from Type System.Object.
public async Task<IActionResult> UploadFileRegistration([FromBody]object incomingObject)
This object I would like to parse into my type.
public class MyType
{
public string name;
public double age;
}
The incoming object can has one more attribute "version" and the content of version can look different each time.
{"name":"Gisela", "age":29.64}
{"name":"Gisela", "age":29.64, "version":"new"}
{"name":"Gisela", "age":29.64, "version":2.0}
{"name":"Gisela", "age":29.64, "version":["param1":17,"param2":"oho"]}
{"name":"Gisela", "age":29.64, "version":true}
In case this object has a child with name "version". I want to remove this child and put it into a string. In the parent object the child should be removed.
How to do this?
I think of some thing what do's that (made-up code)..
private object o;
private string myVersion; //...
if(o.HasChild("version"))
{
myVersion = o.Child("version");
o.DeleteChild("version");
}

Instead of a system.object, I would try using a Newtonsoft.Json.Linq.JObject
I'm not sure if you need to declare your parameter as dynamic or if JObject will work correctly.
Here is an article that describes it. (It is likely out-dated, but somewhere to start.)
Using JSON.NET for dynamic JSON parsing

Related

How to deserialize a model to its type if the Type is supplied

I'm trying to write a function which accepts a serialized json object (which matches an object definition class (model) ) and given the Type, deserialize it to that model.
There are several models,..in the code below I use TCustomerModel (just a class of properties)
From my API(s), I want to call this function, pass it the json object which matches one of my models,
and also pass it the ModelType (i.e. in this case TCustomerModel
Thus far, what I've seen or tried does not work.
as a simple example. (This works, ..but I want a function which can do this just having the Type passed to it and not having to explicitly create myModel on each and every type ).
TCustomerModel myModel = JsonConvert.DeserializeObject<TCustomerModel>(jsonModel);
Code:
public class DeserializeModelValidator
{
public Object ValidateModel (Type objectType, object theModel)
{
objectModel = JsonConvert.DeserializeObject<theModel>, typeof(objectType));
// etc
}
}
Calling Code: (from within an API)
DeserializeModelValidator validator = new DeserializeModelValidator();
validator.ValidateModel(typeof(TCustomerModel), objectModel);
You can create a generic extension method for this.
public static class DeserializeModelValidator
{
public static T ValidateModel<T>(this string serializedJson)
{
var result = JsonConvert.DeserializeObject<T>(serializedJson);
// etc
return result;
}
}
You would call the extension method as:
var myModel = jsonModel.ValidateModel<TCustomerModel>();
I found this, which works. Now all I need is a way of using the Type variable to instantiate a class of that type.
e.g.
useType CLasstype = new useType();
but, thats a different question.
public object DeserializeModelr(string value, Type useType, params JsonConverter[] converters)
{
var result = JsonConvert.DeserializeObject( value, useType, converters);
dynamic DataModel = Convert.ChangeType(result, useType);
etc
}

Why is there a setter property in C# when deserializing JSON?

When deserializing from JSON to C# objects, why is there a setter property when you technically you are only "getting" the property from a deserialized JSON object? Wouldn't it be appropriate to just have:
public class Json
{
public string MyKey { get; }
}
Rather than:
public class Json
{
public string MyKey { get; set; }
}
I'm not 100% clear as to why I need the "set" property there for my use-case?
Thanks for the help.
When you are deserializing, you are taking the values from the json string and setting them in the c# object so you need the setters to populate the object.
If you were serializing the c# object to a json string, then you would only need the getter because you are getting the values from the c# object.
The JSon Deserializer has to create an instance of your objects and restore their state (the values of their properties) from the serialized Json Stream.
In order to do so, It needs to be able to inject those value in the instances, either by setting their properties (for which it needs a public setter) or by passing them as a parameter to an appropriate constructor (one which has a parameter of the same name and type as the value that needs to be set).

Cast instance to generic interface without knowing type

I have a generic interface called IValueBridge which serves as a generic bridge to get the values from any arbitrary object by providing the properties name (also nested properties are possible, e.g. myFoo.MyProp.Name):
public interface IValueBridge<in T> : IValueBridge
{
object GetValue(T instance, string attributeName);
}
Now there is an implementing class:
public class ValueBridge<T> : IValueBridge<T>
{
public object GetValue(T instance, string attributeName)
{
Func<T, object> f = // ...
return f(instance);
}
}
Now with this setting I wanto to use that bridge in order to get the values for any arbitrary object without knowing its type at compile-type.
What I WANT to achieve is something similar to this:
object bar = ...;
var bridge = new ValueBridge<typeof(bar>();
I know how to create instances of generic types via reflection using MakeTypeGeneric. However what Activator.CreateInstance returns is an object and I cannot cast it to the actual type Bar (which I don´t know at compile-time) and thus cannot access GetValue<T> on it.
Is there a way I can access GetValue<T> without any more reflection? I´d like to avoid more reflection as the method is called very often and calling it via reflection is considered quite slow. That´s why I cache the Func<T, object> to be called inside.
I found a quite nice solution using a wrapper-interface which IValueBridge<T> extends:
public interface IValueBridge
{
object GetValue(object instance, string attributeName);
}
Now my actual ValueBridge looks like this:
public class ValueBridge<T> : IValueBridge<T>
{
object IValueBridge.GetValue(object instance, string attributeName)
{
return this.GetValue((T)instance, attributeName);
}
public object GetValue(T instance, string attributeName)
{
Func<T, object> f = // ...
return f(instance);
}
Now you can use ((IValueBridge) myBridge).GetValue(...) . As the parameter can be cast to its actual type within the ValueBridge ((T) instance)) we can now invoke the generic version of the method directly without any reflection.
Note that you have to explicitely implement any of the two interfaces to avoid confusion which method to call from within the wrapper.
The reason I self-answer that question is that I got much head-ache on solving it and want to share the result of my thoughts to the community.

How to serialize class type but not the namespace to a Json string using DataContractJsonSerializer

I'm trying to serialize a class hierarchy to a Json string using DataContractJsonSerializer, in a WCF service.
the default behaviour for serializing a derived class is to add the following key value pair to the object:
"__type":"ClassName:#Namespace"
My problem is that namespaces are long and they bloat the Json string.
I would like to somehow intervene with the serialization and output this instead:
"__type":"ClassName"
and on deserialization intervene again to point to the correct namespace (which i know in runtime).
Is there any way to do such a thing?
This page describes the circumstances under which the __type property is emitted. In short, in WCF, if you use a derived type, and a KnownTypeAttribute, then you're going to get a __type property.
Example:
Assume
[DataContract]
[KnownType(typeof(Subscriber))]
public class Person { ... }
[DataContract]
public class Subscriber : Person { ... }
This code generates a __type property:
var o = new Subscriber("Fleming");
var serializer = new DataContractJsonSerializer(typeof(Person));
serializer.WriteObject(Console.OpenStandardOutput(), o);
But this code does not:
var o = new Subscriber("Fleming");
var serializer = new DataContractJsonSerializer(typeof(Subscriber));
serializer.WriteObject(Console.OpenStandardOutput(), o);
Notice that the second snip uses a DCJS with the same type as the object being serialized.
To avoid the __type, don't use derived types, or to be precise, use a serializer typed to the type you are actually serializing. If the serialization is being performed implicitly by a WCF method, then the method must be typed appropriately. In my example, it means you must use a return type of "Subscriber", and not the parent type, "Person".
The __type is emitted into the JSON stream by the (private) WriteServerTypeAttribute method on the
(internal) System.Runtime.Serialization.Json.XmlJsonWriter class. There is no public, documented, supported way to modify that, as far as I can tell.
To avoid this, you'd maybe need to return a string from the WCF method, perform the serialization yourself, and post-process the emitted JSON.
If you don't mind the __type thing, but just want to remove the qualifying namespace from the value, then put your types in the global namespace. In other words, put them outside of any namespace declaration in code.
Example: When the data types reside in a namespace, and when I used a derived type, the serialized JSON looks like this:
{
"__type":"Subscriber:#My.Custom.Namespace",
"Index":604455,
"Name":"Fleming",
"Id":580540
}
When the data types reside in the global namespace, it looks like this:
{
"__type":"Subscriber:#",
"Index":708759,
"Name":"Fleming",
"Id":675323
}
Adding the namespace parameter to the data contract does the trick.
[DataContract(Namespace = "")]
Cheeso's answer was excellent. I did discover a refinement to cleaning up the __type field though:
Rather than removing your subclass from its namespace you can add a property like the following:
[DataMember(Name = "__type")]
public string SubclassType
{
get
{
return "Subscriber";
}
set { }
}
You still get stuck with the ugly name "__type" but I found that because I was returning a list of subtypes I wanted to specify the type name anyway. You could even return a value of "" to further reduce response size. You could also just declare the property as:
public string __type
but I found that to accentuate the hack so I stuck with an appropriate property name and then renamed it.
-Joey
Note: I typed up this answer below and later realized that DataContractResolver is currently not supported with DataContractJsonSerializer. It may soon be with the next release of the framework, however. This is also useful if you are looking at more than just JSON.
**
You can do this with a DataContractResolver, which lets you map types to xsi:type (__type) information and vice-versa in a custom manner.
To do this, check out this blog post on DataContractResolver, plus this conceptual topic, plus this sample
#Cheeso wrote:
To avoid this, you'd maybe need to return a string from the WCF
method, perform the serialization yourself, and post-process the
emitted JSON.
Here's how I implemented that post-processing. I thought I'd post it here JIC it might help someone else.
First some boilerplate to show how I generate my JSON string:
// Instantiate & populate the object to be serialized to JSON
SomeClass xyz = new SomeClass();
... populate it ...
// Now serialize it
DataContractJsonSerializer ser = new DataContractJsonSerializer(xyz.GetType()); // Note xyz.GetType()
... serialize the object to json, many steps omitted here for brevity ...
string json = sr.ReadToEnd();
(Serialization is based on examples from https://msdn.microsoft.com/en-us/library/bb412179%28v=vs.110%29.aspx )
Note that the [DataContract] on SomeClass does not include the (name="") syntax that I've seen suggested elsewhere. That only removes the namespace from the __type at the cost of needing to adorn ALL your DataContract attrs, which clutters your code. Instead, my post-processor handles the assembly name in the __type field.
And now the string json contains the JSON text, but unfortunately includes all that "__type" junk that you don't want but can't suppress.
So here's my post-processing code that removes it:
// This strips out that unsuppressable __type clutter generated by the KnownType attributes
Attribute[] attrs = Attribute.GetCustomAttributes(xyz.GetType());
foreach (Attribute attr in attrs)
{
if (attr is KnownTypeAttribute)
{
KnownTypeAttribute a = (KnownTypeAttribute)attr;
string find = "\"__type\":\"" + a.Type.ReflectedType.Name + "." + a.Type.Name + ":#" + a.Type.Namespace + "\",";
json = json.Replace(find, "");
}
}
This makes a few assumptions, most notably that the __type field ends with a comma, which assumes that another field follows it, though (a) my objects always have at least 1 field and (b) I've found that the __type field is always 1st in the serialized object's output.
As always, you may have to adjust something to your situation, but I find it works well for mine.
Some times ago i decided this problem.
I use DataContractJsonSerializer
You will have __type in json, if your method for serialization have Base class parameter, but you give it subClass as parameter.
More details:
[DataContract]
[KnownType(typeof(B))]
public abstract class A
{
[DataMember]
public String S { get; set; }
}
[DataContract]
public class B : A
{
[DataMember]
public Int32 Age { get; set; }
}
public static String ToJson<T>(this T value)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, value);
return Encoding.UTF8.GetString(stream.ToArray());
}
}
You have two methods for test:
public static void ReadTypeDerived(A type)
{
Console.WriteLine(ToJson(type));
}
and
public static void ReadType<T>(T type)
{
Console.WriteLine(ToJson(type));
}
In first test you wiil have
"{\"__type\":\"B:#ConsoleApplication1\",\"S\":\"Vv\",\"Age\":10}"
In second:
"{\"S\":\"Vv\",\"Age\":10}"

Can I implement a generic type and pass it a type that is known only at runtime?

I'm pulling serialized data from a database along with an object type (where one field contains the object type and one contains an XML string of serialized data).
I've got a generic serializer that has a serialize and deserialize method:
public static class Serializer<T>
{
public static string Serialize(T objectData) { }
public static T Deserialize(string xmlData) { }
}
Given that the object type is specified in the database field, is there any way for me to dynamically set what T is? - This is my line of thought (although this doesn't work):
Type t = Type.GetType(objectTypeName);
t objData = Serializer<t>.Deserialize(objectXmlString);
I was hoping to refactor some code out of a switch statement where T is a set value, but I can't figure out if it can be done, or if so, how I would go about that.
Thanks in advance.
You can do this, but it involves reflection - MakeGenericType, in particular:
typeof(Serializer<>).MakeGenericType(t).GetMethod("Deserialize").Invoke(...);
I haven't completed that, since your example is confusing; the method is instance, but is called as though it were static.
Interestingly (perhaps), dynamic might make this easier in 4.0 - I don't have my VM to hand, but imagine:
static void SomeGenericMethod<T>(T arg) { Serializer<T>.SomeMethod(arg); }
...
dynamic obj = ...
SomeGenericMethod(obj);
I'd need to check, but I expect that would do a lot of the heavy lifting for us.
The other common approach is to expose methods that work on a Type, rather than via generics.
No. However, it should not be too difficult to create additional overloads of your serialisation methods to handle this requirement:
public string Serialize(Type objectType, object objectData) { }
public object Deserialize(Type objectType, string xmlData) { }
The serialisation APIs in .NET all take Type instances as parameters anyway.

Categories

Resources