Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing with Json.Net, deserialize sub-object into string/similar holding the json?

Tags:

c#

json.net

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.

like image 257
Lasse V. Karlsen Avatar asked Jan 12 '15 21:01

Lasse V. Karlsen


People also ask

How do I deserialize a JSON string to an object in C#?

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.

What is JSON Deserializing?

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).

What is serializing and deserializing JSON in C#?

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.

What is the use of JsonConvert DeserializeObject?

Deserializes the JSON to the specified . NET type. Deserializes the JSON to the specified . NET type using a collection of JsonConverter.


1 Answers

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.

like image 58
Jon Skeet Avatar answered Sep 22 '22 10:09

Jon Skeet