3

Basically I am after C# equivalent of the following JavaScript syntax:

var obj = {id: 1};
obj["prop1"] = 100;
obj["prop2"] = 200;

Is it possible to add properties to C# object dynamically and serialize to JSON using WebAPI controller action?

My C# object:

public class MyObject
{
    public int Id { get; set; }
    public MyChildObject[] Chidren { get; set; }

    public int this[string prop]
    {
        get { return Chidren.Single(x => x.PropertyName == prop).Value; }
    }
}

public class MyChildObject
{
    public string PropertyName { get; set; }
    public int Value { get; set; }
}

What I'd like to return to the client is this:

{
    id: 1,
    prop1: 100,
    prop2: 200
}

This test passes but obviously only because the properties are accessed at runtime. They are not, however, serialized:

[TestMethod]
public void CanAccessDymaicProperties()
{
    var dto = new MyObject
    {
        Id = 1,
        Chidren = new[]
        {
            new MyChildObject { PropertyName = "prop1",  Value = 100 },
            new MyChildObject { PropertyName = "prop2",  Value = 200 },

        }
    };

    Assert.AreEqual(dto["prop1"], 100);
    Assert.AreEqual(dto["prop2"], 200);
}
Ruslan
  • 9,927
  • 15
  • 55
  • 89
  • 2
    Possible duplicate of [Can I serialize an ExpandoObject in .NET 4?](http://stackoverflow.com/questions/4853574/can-i-serialize-an-expandoobject-in-net-4) – Eris Jul 01 '16 at 16:26
  • 1
    Have a look at `ExpandoObject`; https://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v=vs.110).aspx – Dmitry Bychenko Jul 01 '16 at 16:26
  • 2
    In addition to the answers given below you can use anonymous types and do things like this var x = new { id = 1, name= "Tom", numbers = new[] { 1,2,3} }; This kind of objects can be returned as Json from a webapi and consumed from Javascript at client side. See http://stackoverflow.com/questions/10123371/returning-anonymous-types-with-web-api – derloopkat Jul 01 '16 at 16:39

2 Answers2

8

You can use an ExpandoObject and the dynamic keyword:

dynamic o = new ExpandoObject();
o.Prop1 = 100;
o.Prop2 = "Sample";
JsonConvert.SerializeObject(o); // {"Prop1":100,"Prop2":"Sample"}

If you just need to serialize a custom collection of key/value pairs, you should use a Dictionary<string, object>:

var dic = new Dictionary<string, object>();
dic["Prop1"] = 100;
dic["Prop2"] = "Sample";
JsonConvert.SerializeObject(dic); // {"Prop1":100,"Prop2":"Sample"}

As said in comments by @derloopkat, you can also use an anonymous object:

var o = new { Prop1 = 100, Prop2 = "Sample" };
JsonConvert.SerializeObject(o);
meziantou
  • 20,589
  • 7
  • 64
  • 83
3

This sounds like a good job for Dictionary, or any associative data structure. You don't need to get fancy, you just need a map where the keys are strings (i.e. field names) and the values are whatever you want.

This structure is readily converted to JSON and visa-versa.

Dictionary description

Check out this SO Thread for examples on Dictionary to JSON serialization

Community
  • 1
  • 1
nlloyd
  • 1,966
  • 2
  • 15
  • 18
  • 1
    that's what I was going to say, his code is basically var obj = new Dictionary { { "id", 1} }; obj["prop1"] = 100; obj["prop2"] = 200; – derloopkat Jul 01 '16 at 16:28
  • i tried extending a dictionary to achieve a flat structure but it somehow loses the rest of the properties (e.g. Id) `MyObject: Dictionary` – Ruslan Jul 01 '16 at 16:55
  • I'm not exactly sure what you mean, but if you're trying to combine different "objects" into the same dictionary, yes the values will get overwritten. Just think how JSON handles collections; you have an array of dictionarys (i.e. javascript objects) if you are trying to represent several of them. – nlloyd Jul 01 '16 at 17:01