I have a code that takes messages of any type and serialize them into the DB, while saving the type of the message and the serialized json string.
I have a side process that should deserialize the messages later on and send them to the queue.
To perform the serialization and deserialization I use JsonConvert of Newtonsoft.Json:
For deserialization I use the following method:
object? DeserializeObject(string value, Type type)
For serialization I use the following method:
string SerializeObject(object? value)
I have the following questions:
A. I saw that in case DeserializeObject receives a wrong type name it still deserialize the object but his type is Newtonsoft.Json.Linq.JObject and not the type I passed into the method, I expected it will throw an exception, this behavior is very bad for us, is there any way to cause the deserialize to throw exception in this scenario?
B. Is the code below secured? I saw that the library has variabilities such as depicted here
private void StackOverflowQuestion()
{
Bus.Employees.Messages.LevelCreated levelCreated = new Bus.Employees.Messages.LevelCreated
{
Name = "director",
};
//var messageType = levelCreated.GetType().AssemblyQualifiedName;
string messageData = JsonConvert.SerializeObject(levelCreated);
//Deserialize with type that is not correct
object deserializeMessaged = DeserializeMessage("my cool type which does not exists!", messageData);
string theType = deserializeMessaged.GetType().FullName;//theType = Newtonsoft.Json.Linq.JObject
}
private object DeserializeMessage(string messageType, string messageSerializedData)
{
Type type = Type.GetType(messageType);
return JsonConvert.DeserializeObject(value: messageSerializedData, type);
}
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).
I want to understand how Json.NET deserializes a JSON object to corresponding c# object when we have multiple property names with different cases(I know this is not a good practice, but just curious to know how JSON.NET deals with this).
I have a c# object defined as below:
public class TestModel
{
public string Name { get; set; }
public bool IsEmployee { get; set; }
}
And json object as
{ "Name": "TestName","Isemployee":true, "isemployee":false};
Then, if I use the JSON.NET de-serialize method to convert above json string to TestModel object, which one of those two properties will be assigned to IsEmployee variable? And why?
Thanks.
In deserialization, Json.NET attempts case insensitive matching of an attribute if exact matching fails, as discussed here. This is in contrast to the built-in .NET JSON serializers, see here.
If multiple matches are detected, the last match takes precedence.
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}"
I am using the .NET JavascriptSerializer class for a while now to serialize my object to a JSON representation and use it on the client side. Everything works great as long as I stick with the default types like int, string, etc. However, now I want to serialze a custom type property on my object. Let look at an example of my class:
public class ClientData
{
public Guid Id { get; set; }
public string Description { get; set; }
public MyCustomObject ObjectX { get; set; }
}
Wat I want is a clientside object that looks something like this:
{ Id: 0000-0000-000-0000, Description: "some description", ObjectX: "125.20" }
To make this work, I tried using a JavaScriptConverter but that doesn't seem to solve the problem because it can only handle dictionaries, what will make the result look like this:
{ Id: 0000-0000-000-0000, Description: "some description", ObjectX: { Value: "125.20"} }
That's not what I want. I did implement the toString on the MyCustomObject class by the way.
Any suggestions?
Thanks allot.
here is the msdn page to javascriptserializer:
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
in the remark section it says:
To serialize an object, use the Serialize method. To deserialize a JSON string, use the Deserialize or DeserializeObject methods. To serialize and deserialize types that are not natively supported by JavaScriptSerializer, implement custom converters by using the JavaScriptConverter class. Then register the converters by using the RegisterConverters method.
so you should look at this class:
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptconverter.aspx
Using a JsonConverter from the Json.NET library seems to do the trick for me.
You can convert a custom object into a string. You use a JavaScriptConverter that converts your object into a Uri instance that also implements IDictionary to allow it to pass out of the JavaScriptConverter.
This hack is described for DateTime objects here:
http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/