I need to create a class in runtime with properties based on a list of strings.
I then need to populate this new class with values before I serialize it.
Have looked at dynamics in C# and also anonymous types but can't get it to work.
Any help appreciated.
Thanks!
//1. List of string with the properties I need
List<string> properties = new List<string>();
properties.Add("Id");
properties.Add("Name");
//2. Create class called className with properties above
//todo
//3. Populate with values
//todo
//4. Serialize to JSON
JavaScriptSerializer jScriptSerializer = new JavaScriptSerializer();
string jsonString = jScriptSerializer.Serialize(className);
The task of turning text into classes traditionally belongs to two parts of the system: compilation and serialisation. That makes for several methods I can think of.
Compilation using Reflection.Emit. The class to start with is TypeBuilder, but you'll need several more.
Compilation using Roslyn. Roslyn exposes an API for dynamic compilation.
Compilation using the C# compiler. Create a valid program as a string and compile it. Pull the type you need out of the assembly using System.Type.
Deserialisation via JSON. Create a valid JSON object as a string and deserialise it.
Deserialisation via XML. Create a valid XML schema as a string and deserialise it.
I would use Reflection.Emit because I'm familiar with it, but they are all more or less feasible.
Related
I have a Json schema and can use NJsonSchema.CodeGeneration.CSharp to create classes corresponding to it. So if I have json which conforms to the schema, I should be able to easily parse it into a collection of objects whose classes are the classes generated from the schema?
So how can I do this - parse json and get out C# class objects that correspond to the objects in the json (as define by the schema)?
As an example - if the schema defines a first object definition which is an array of a second object definition, then I would like to be able to parse it in such a way that the output is an instance of the class corresponding to the first object definition and it has a member which is a List of instances of the class corresponding to the second definition. It seems that the schema knows all the information required to do this, so it should be a single line - I appreciate I could do long-hand parsing (eg converting each item in the array) to achieve the same result.
I would think this would be a primary purpose of having C# classes generated from a schema, so what's the magic method I'm missing?
I'm also happy to write C# classes and generate a schema from that if it's a more workable solution.
I've used NJsonSchema but happy to use any other C# json schema and code generation technique that achieves the same end.
UPDATE: After discussion I've seen that if NJsonSchema is used to generate classes from the schema, the TypeScript version of those classes each have a fromJS method which sounds like what I want but they're missing from the C# version. I'm happy to use something other than NJsonSchema to generate classes from schema if it provides a solution.
I think I found the answer, which was a lot simpler than I had anticipated. It's simply to use something like:
var ob=JsonConvert.DeserializeObject<MyNamespace.Anonymous>(jsonString);
...where MyNamespace is the namespace of the generated C# classes, MyNamespace.Anonymous is the class corresponding to the root of the schema (default names from NJsonSchema), and jsonString the string to be parsed.
I thought the solution would need to be schema-aware, since it would need to know about all the classes created from the schema, but I guess it 'works that out' from reflecting on the Anonymous class it's given and where the properties of it are classes, reflecting on those and so on.
I was over-thinking the problem!
Recently I need to parse JSON object like this:
{
"method":"someMehtod",
"content":{"oneObject":"can be a very complicated object"},
"somotherthing":"someOtherValue"
}
into C# with Newtonsoft JSON.NET.
I know it is very common to create a new class or classes for the purpose but this is highly unwelcome choice to my current situation since it is considered unnecessary to my superior (and I don't want there to be too many classes like this either). Is there anything that resembles JAVA's JSONObject class in C# world I can use to query multiple level json without making new class?
You can use JSON.Net's JObject. Here's an example:
var jsonString = "{\"method\":\"someMehtod\", \"content\":{\"oneObject\":\"can be a very complicated object\"}, \"somotherthing\":\"someOtherValue\"}";
var obj = JsonConvert.DeserializeObject<JObject>(jsonString);
Console.WriteLine(obj["content"]["oneObject"]); // will print "can be a very complicated object"
dotnet fiddle demo available here
Take a look at the JsonConvert.DeserializeAnonymousType method. Define an anonymous type inline to define the expected structure and pass it in as a parameter. No new classes required, but I suspect if your superior is against creating new classes (really??) then they'll be against anonymous types too...
https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm
I have reference to several classes defined in an external library that contain a TypeConverter attribute. Due to this attribute, Json.Net, and consequently Nest, is incorrectly serializing these objects. The correct way to serialize these objects is to ignore the TypeConverter attribute and make use of the object properties. In searching Stack Overflow I have found a method that successfully does this.
Unfortunately, when I apply this method to Nest in the following way, the resultant objects do not contain the necessary _type, _index and _id fields.
var settings = new ConnectionSettings(_Uri);
// Tell Json.Net to ignore custom TypeConverters
settings.SetJsonSerializerSettingsModifier(m => m.ContractResolver = new SerializableContractResolver());
var client = new ElasticClient(settings);
Since the resultant JSON does not contain the critical fields, all index requests fail. Is there a way to have Nest ignore the TypeConverter attributes while still ensuring the objects contain the necessary additional fields for Elasticsearch requests?
When you are passing a contractresolver that ignores TypeConverters you are applying a bazooka to kill a fly in my opinion.
We also rely heavily on typeconverters to write our objects correctly.
If the classes in your external library do not quite represent the way they should look in your elasticsearch index I'd recommend create a specific POCO for NEST that does. AutoMapper is a great way to convert instances of your external library to instances of indexable object.
#Martijn Laarman's suggestion is probably the correct solution. However, I decided to unblock myself with the following hack:
I continue to use the method defined here. I then correctly serialize the external object into JSON. I deserialize the object into a dynamic type. Finally I pass this object to Nest.
// Strip away TypeConverter attributes -- super hacky
var json = JsonConvert.SerializeObject(item);
payload = JsonConvert.DeserializeObject<dynamic>(json);
descriptor.Index<Object>(op => op.Index(index).Type(type).Id(id).Document(payload));
I am converting code that was written using NewtonSoft.JsonNet. This is actually a custom Json Media Type Formatter. I have to change it because Json.Net has proven that its performance is very poor under load. Many comparison on the Internet is also proving this.
Anyway, I have a base type called CatalogueItem. Three types are derived from this type and are called ContainerItem, SectionItem, and RefresherItem. Based on a property in the Json object which is called itemType we decide which sub-class must be instantiated.
var type = (string)jsonObject.Property("itemType");
switch (type)
{
case "Container":
return new ContainerItem();
case "Section":
return new SectionItem();
case "Refresher":
return new RefresherItem();
}
We used to do this with creating a custom CustomCreationConverter, and adding it to Serializer.Converters collection of Json.Net.Serializer. Trying to get rid of Json.Net, I am using ServiceStack.Text, but I don't know how can I control the type that is being generated using it. Can anyone please help me with this?
p.s. I found this post on StackOverflow in which similar issue has been answered. However, I get the json from a third-party web service so I cannot include type names in it. Plus, I cannot use the generic version of JsConfig because MediaTypeFormatter does not have any generic methods.
I recommend avoiding trying to coerce your JSON Serializer to your models and just use DTO's that map 1:1 to the wire format than use plain C# to map the typed DTO's to your desired domain models.
With that said, depending on what the JSON and DTO's look like you may be able to use one of:
JsConfig<CatalogueItem>.RawDeserializeFn
JsConfig<CatalogueItem>.DeSerializeFn
JsConfig<CatalogueItem>.OnDeserializedFn
Otherwise you can parse JSON dynamically using JsonObject, here's an example.
I am in the process of designing an itemization system for a game. I am creating a bunch of interfaces (IItem, IConsumable, IEquipable, IWeapon, etc...) to define what type of functionality is possible with items and then a number of classes (Weapon, Potion, etc...) the define the actual item types.
Now when saving out the player, the data is going to be stored as a JSON file (using the JSON.NET library) and will included the players inventory which will include these items. The issue is that when I try to deserialize the JSON file to an object when reading in the file, how will I be able to tell the JSON.NET library what type of class this is?
One thing I thought of and have not had time to try yet is that all my objects that get serialized into JSON have a DTO version of the object that is used in conjunction with the JSON.NET library. What I though about trying is maybe I could add in a property to the DTO called ClassType and then when reading the file into the application, I would first read the object in as an anonymous type. Then based on the ClassType property, I would convert it to the proper type. The 2 issues I have with this is that 1. it seems like a very ugly solution and 2. I am not even sure if that is possible.
(Copied from this question)
In cases here I have not had control over the incoming JSON (and so cannot ensure that it includes a $type property) I have written a custom converter that just allows you to explicitly specify the concrete type:
public class Model
{
[JsonConverter(typeof(ConcreteTypeConverter<Something>))]
public ISomething TheThing { get; set; }
}
This just uses the default serializer implementation from Json.Net whilst explicitly specifying the concrete type.
The source code and an overview are available on this blog post.
You should know the concrete type when you are serializing. So you can use TypeNameHandling of JSON.NET.
http://james.newtonking.com/archive/2010/08/13/json-net-3-5-release-8-3-5-final.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+jamesnewtonking+%28James+Newton-King%29