I am trying to create a configuration file using Json that will hold configuration for various types of objects.
Consider this file:
{
"cameras": [
{
"type": "Some.Namespace.CameraClass",
"assembly": "Some.Assembly",
"configuration": {
"ip": "127.0.0.1",
"port": 8080
}
}
]
}
At runtime I will use the two "type" and "assembly" properties to construct an object supporting a specific interface, and then I would like to load the configuration into that object.
However, at compile time I do not know the type that "configuration" would map to. I would like to retain it as a json "property" and feed that into the camera object, and then let that object deserialize the json into the right type.
As such I would like to just "carry" the part of the configuration file containing configuration for a particular camera type with me into the object itself, and let it deal with it, treating it like a black box while I carry it like that. The structure of that part should be preserved since I would like full fidelity when creating the configuration types for each camera implementation, even adding subobjects if necessary.
For this particular camera I would configure an IP address and a port, for some other camera I would require authorization data, and for some other camera something completely different.
I would like for the property that would hold this configuration to just get the Json directly, still as a string.
Is this possible?
Here is a LINQPad example that has some bits commented out:
void Main()
{
const string configurationFile = @"[
{
""type"": ""UserQuery+Camera1"",
""configuration"": { ""id"": 10 }
},
{
""type"": ""UserQuery+Camera2"",
""configuration"": { ""name"": ""The second camera"" }
}
]";
var cameras = JsonConvert.DeserializeObject<Camera[]>(configurationFile);
foreach (var camera in cameras)
{
var type = Type.GetType(camera.Type);
var instance = Activator.CreateInstance(type, new object[0]) as ICamera;
// instance.Configure(camera.Configuration);
}
}
public class Camera
{
public string Type { get; set; }
public JObject Configuration { get; set; }
}
public interface ICamera
{
void Configure(string json);
}
public class Camera1 : ICamera
{
private class Configuration
{
public int Id { get; set; }
}
public void Configure(string json)
{
JsonConvert.DeserializeObject<Configuration>(json).Dump();
}
}
public class Camera2 : ICamera
{
private class Configuration
{
public string Name { get; set; }
}
public void Configure(string json)
{
JsonConvert.DeserializeObject<Configuration>(json).Dump();
}
}
The two commented out bits, namely the property in the Camera
class, and the call to the Configure
method, is what I'd like working.
Is there something I can tag that property with, or some other type I can pick for that property, that would make this work?
I know I can make the property dynamic, which would stuff a JObject
into it, but then each Configure
method of each camera implementation would have to deal with a JObject
and not a known non-dynamic type.
A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
Json structure is made up with {}, [], comma, colon and double quotation marks and it includes the following data types: Object, Number, Boolean, String, and Array. Serialize means convert an object instance to an XML document. Deserialize means convert an XML document into an object instance.
Deserializes the JSON to the specified . NET type. Deserializes the JSON to the specified . NET type using a collection of JsonConverter.
It looks like if you use a property of type JObject
, that parses but preserves the JSON:
using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Foo
{
public string Name { get; set; }
public int Age { get; set; }
public JObject Configuration { get; set; }
}
public class Test
{
public static void Main()
{
var json = File.ReadAllText("test.json");
var foo = JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine(foo.Configuration);
}
}
Test.json:
{
"name": "Jon",
"age": 10,
"configuration": {
"ip": "127.0.0.1",
"port": 8080
}
}
Output:
{
"ip": "127.0.0.1",
"port": 8080
}
I suspect you can deserialize straight from the JObject
, but you can always convert it back to a string
if you really want to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With