I'm receiving messages over a network using JSON.NET. The message format is somewhat dynamic, in that the messages will be represented by many different classes, each inheriting from a parent message. For example:
{
MessageName: "MessageType1",
Data1: 124,
Data2: "Something"
}
{
MessageName: "MessageType2",
OtherData: "Some data",
MoreData: "Even more",
ANumber: 25
}
The problem I'm having is that in JSON.NET, I have no idea how to figure out the name of the class (MessageType1/MessageType2/etc) in order to deserialize it into an instance of the class without deserializing it twice. There's a few options I've considered; the one I'm currently using is to use a container class containing the message name and the actual json message serialized to string, but this seems wasteful.
Another method I've considered is deserializing into a string/string dictionary and then performing the population of the class on my own, which seems messy and unnecessary considering JSON.NET can do that for me... as long as I know the class first.
I'm really hoping there's an easy way to have JSON.NET figure out a class name by examining the MessageName property and then continue to populate a class after examining that one property.
Thanks for the help!
JSON can deserialize into a well known class only. You need to specify the data layout (i.e. the class/type)
There are two alternatives:
1.) go one level deeper. Use the JSON Token parser to read the tokens from your JSON stream and act based on the tokens you find.
2.) as you suggested: Use a class layout flexible enough to hold all your possible variations like a key/value dictionary.
Related
the problem is that i dont know how to create model for json from api.
I used some online json to c# generator but it creates a very high count of classes what is unnecessary and very problematic with time.
thats my json:
https://solomid-resources.s3.amazonaws.com/blitz/tft/data/items.json
Fixed with this model
https://pastebin.com/SpGe72P7
and this serialization line
Dictionary<string, TftItems> foo = Drzewo.Configuration.DeserializeJson<Dictionary<string, TftItems>>(data);
where Configuration.DeserializeJson is just generic function of
JsonConvert.DeserializeObject<T>(json)
I have a set of objects that contain fields & properties that need to be inspectable in the output of serialization but not read back in when deserialized.
This is purely for debugging/confirmation purposes. We are creating hundreds of files and I want to spot check that serialization is occurring correctly by adding supplementary information. I do not want this supplementary information to be read in during deserialization - it's impossible to do so in fact.
I also need to do this with equal facility across different serialization formats, so we can assess which one is working best. I have a generic serialization approach where the desired format is passed in as an argument, so don't want anything too messy or intricate for each different format.
I've hunted around and found various things on related topics - mostly to do with the opposite: not writing certain fields during serialization. What's out there seems to be quite complicated and at times hacky.
Is it possible to serialize an object differently to deserializing it using Json.Net?
JsonConvert .NET Serialize/Deserialize Read Only
Serialize Property, but Do Not Deserialize Property in Json.Net
Also it appears any approach is inconsistent between serialization formats. i.e. unlike the [*Ignore] attributes, there are no [*SerializeOnly] attributes (where * = JSON, XML, YAML).
Is there an easy way to do this across these serialization formats? Is there a single family of attributes that can help? Or is it idiosyncratic and hacky in each case?
I have tested and applied this only to XML serialization, but it works for me:
When I want a property to be serialized, but not read back, I just declare an empty setter.
public String VersionOfApplicationThatHasWrittenThisFile
{
get
{
return "1.0";
}
set
{
// Leave empty
}
}
I have a json structured like that:
{
"eventType1": {
"unitName": "nameValue",
"comment": "initial comment"
},
"eventType2": {
"comment": "initial message"
},
}
When I deserialize it the appropriate type seems to be something like Dictionary<string, <Dictionary<string,string>>> and method would look like that:
public static Dictionary<string, Dictionary<string, string>> defaultFieldDataByEvent =
JsonConvert
.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(defaultFieldDataByEventSerialized);
which looks, well, ugly. But that's exactly how I need it to extract the data - defaultFieldDataByEvent[eventType][field].
Can I encapsulate the type into something somehow or is there a different approach to such cases?
I see multiple possible options here. Hope any of these helps.
You may try to add a type alias with using directive to make code shorter, but this won't be convenient, if logic is spread across multiple files, because you will be forced to duplicate this alias.
You may try to use JObject.Parse for deserialization, staying on lower level. But as far as your json structure is pretty various, this approach may work well.
You may try to deserialize your data into ExpandoObject. It's rather similar to JObject, except you will get pretty nice dynamic code (dynamic is not a problem here since compiler won't help you with Dictionary either), but it, obviously will be less performant. You could lose your custom types information, since everything in your graph will become an ExpandoObject, but seems like that's not an issue for your case. Example may be found here.
You may try to use [JsonExtensionData] as #dbc suggested. See How to serialize a Dictionary as part of its parent object using Json.Net.
During WebAPI Response processing, we need to log the response/request body and headers with the security properties being skipped. With Newtonsoft Json, Since the actual response should contain the properties, "Ignore" attribute cannot be placed. We have implemented general filter to handle all Web API Methods that takes excluded property key names as list. Following are approaches tried.
Doing Jobject.Parse and traversing through JTokens and excluding.
Using JsonTextReader and applying conditions while reading.
Both are taking milli seconds time which was not acceptable because its just for logging.
Is there any Optimal way to acheive this?
Create a base class without the security property, use the base class for logging the data and the child one to have everything.
Or create an interface from your class and create a new class with Ignore attribute which you use to log the result.
I want to make a Configuration Data Manager. This would allow multiple services to store and access configuration data that is common to all of them.
For the purposes of the Manager, I've decided to create a configuration class object - basically what every configuration data entry would look like:
Name, type, and value.
In the object these would all be strings that discribe the configuration data object itself. Once it has gotten this data from its database as strings, it would put it into this configuration object.
Then, I want it to send it through WCF to its destination. BUT, I don't want to send a serialized version of the configuration object, but rather a serialized version of the object discribed by the configuration object.
The reason I'd like to do this is so that
The Data Manager does not need to know anything about the configuration data.
So I can add configuration objects easily without changing the service. Of course, I should be able to do all of the CRUD operations, not just read.
Summary:
Input: string of name, type and value
Output: Serialized output of the object; the object itself is "type name = value"
Questions:
Is this a good method for storing and accessing the data?
How can I/can I serialize in this manner?
What would the function prototype of a getConfigurationData method look like?
I have decided to go in a different direction, thanks for the help.
Is this a good method for storing and accessing the data?
That is difficult to answer, the best I can give you is both a "yes" and a "No". Yes, It's not a bad idea to isolate the serialization/rehydration of this data.... and No, I don't really care much for the way you describe doing it. I'm not sure I would want it stored in text unless I plan on editing it by hand, and if I'm editing it by hand, I'm not sure I'd want it in a database. It could be done; just not sure you're really on the right track yet.
How can I/can I serialize in this manner?
Don't build your own, never that. Use a well-known format that already exists. Either XML or JSON will serve for hand-editable, or there are several binary formats (BSON, protobuffers) if you do not need to be able to edit it.
What would the function prototype of a getConfigurationData method look like?
I would first break-down the 'general' aka common configuration into a seperate call from the service specific configuration. This enables getConfigurationData to simply return a rich type for common information. Then either add a extra param and property for service specific data, or add another method. As an example:
[DataContract]
public class ConfigurationInfo
{
[DataMember]
public string Foo;
...
// This string is a json/xml blob specific to the 'svcType' parameter
[DataMember]
public string ServiceConfig;
}
[DataContract]
public interface IServiceHost
{
ConfigurationInfo GetConfigurationData(string svcType);
}
Obviously you place a little burden on the caller to parse the 'ServiceConfig'; however, your server can treat it as an opaque string value. It's only job is to associate it with the appropriate svcType and store/fetch the correct value.