Home > database >  Model creation issues with dictionary and objects
Model creation issues with dictionary and objects

Time:03-24

I have a json object that I need to post to a gateway. It looks as follows.

{
  "client_id": "test",
  "non_personalized_ads": false,
  "events": [
    {
      "name": "test",
      "params": {
        "items": [
          {
            "itemitem1": "itemitem1value",
            "itemitem1number": 1
          }
        ],
        "stringparm1": "stringValue1",
        "intparm1": 1
      }
    }
  ]
}

I am trying to create this as a object class in my C# project. The issue is that both the names of these parms are configurable. So none of these are static property names.

  • "itemitem1": "itemitem1value",
  • "itemitem1number": 1
  • "stringparm1": "stringValue1",
  • "intparm1": 1

So in an attempt to achieve that I went with a Dictionary<string, object> as the value can be a number or a string I went with an Object.

public class EventParameter
{
    public Dictionary<string, object> Parameters { get; set; }
    public Dictionary<string, object> Items { get; set; }
    public EventParameter()
    {
        Parameters = new Dictionary<string, object>();
        Items = new Dictionary<string, object>();
    }

    public void AddEventParameter(string name, object value)
    {
        Parameters.Add(name, value);
    }
}

unfortunately when I do a json pars on this I get. Which is incorrect as my Parameters should be under parms and not under their own object.

{
  "client_id": "test",
  "non_personalized_ads": false,
  "events": [
    {
      "name": "hit_event",
      "params": {
        "Parameters": {
          "TestString": "test",
          "testInt": 1
        },
        "Items": {
          "test": 1,
          "test2": 1,
          "test3": "test"
        }
      }
    }
  ]
}

So how do i get Parameters moved up to parms? It feels like parms needs to be a Dictionary<string, object> but then its going to be missing its items list

 "Parameters": {
          "TestString": "test",
          "testInt": 1
        },

Im assuming there's something missing in my model design. I have been looking at this too long i cant come up with the solution. My other idea was could this be done by adding a custom json sterilizer?

Let me know if you want my full model design or the unit test I am using to test with.

unit test

[Fact]
public void Test1()
{

    var postData = new Event() { Name = "EventName" };
    postData.EventParameters.AddEventParameter("TestString", "test");
    postData.EventParameters.AddEventParameter("testInt", 1);
    postData.EventParameters.Items = new Dictionary<string, object>()
    {
        { "test", 1 },
        { "test2", 1 },
        { "test3", "test" },
    };
    
    var data = new EventData()
    {
        ClientId = "test",
        Events = new []
        {
            postData
        }
    };
    
    var options = new JsonSerializerOptions { IgnoreNullValues = true };
    var hold =JsonSerializer.Serialize(data);

    // add breakpoint here
    int i = 1;

}

CodePudding user response:

Here's a class that serialises to the first json you showed:

class X 
{
    public string client_id {get; set;}
    public bool non_personalized_ads {get; set;}

    public List<EventParameter> events { get;set;}
}

class EventParameter {
    public string name {get; set;}

    
    public Dictionary<string, object> @params {get; set;}
}

Test code:

var x = new X 
{
    client_id = "test",
    non_personalized_ads = false,
    events = new List<EventParameter>{
        new EventParameter
        {
            name = "test1",
            @params = new Dictionary<string, object>{
                { "items", new Dictionary<string, object> {
                        {"itemitem1", "itemitem1value"},
                        {"itemitem1number", 1}
                    }},
                { "stringparm1", "stringValue1"},
                {"intparm1", 1}
            }
        }
    }
};

var json = System.Text.Json.JsonSerializer.Serialize(x, options: new System.Text.Json.JsonSerializerOptions{WriteIndented = true});
Console.WriteLine(json);

CodePudding user response:

try this

    var events = JsonConvert.DeserializeObject<EventData>(json);

test

json=JsonConvert.SerializeObject(events, Newtonsoft.Json.Formatting.Indented);

{
  "client_id": "test",
  "non_personalized_ads": false,
  "events": [
    {
      "name": "test",
      "params": {
        "items": [
          {
            "itemitem1": "itemitem1value",
            "itemitem1number": "1"
          }
        ],
        "stringparm1": "stringValue1",
        "intparm1": 1
      }
    }
  ]
}

or if you don't know how to create an object from class

var eventData = new EventData()
    {
        ClientId = "test",
        Events = new List<Event>
        {
           new Event{
            Name="test",
            Parameters= new Dictionary<string, object>()
           }
        }
    };

    var items = new List<Dictionary<string, object>>();
    items.Add(new Dictionary<string, object>());
    items[0].Add("test1", "test1");
    items[0].Add("test2", 2);

    eventData.Events[0].Parameters.Add("items", items);
    eventData.Events[0].Parameters.Add("testString", "test");
    eventData.Events[0].Parameters.Add("testInt", 1);

result

{
  "client_id": "test",
  "non_personalized_ads": false,
  "events": [
    {
      "name": "test",
      "params": {
        "items": [
          {
            "test1": "test1",
            "test2": 2
          }
        ],
        "testString": "test",
        "testInt": 1
      }
    }
  ]
}

classes

public class EventData
{
    [JsonProperty("client_id")]
    public string ClientId { get; set; }
    [JsonProperty("Non_personalized_ads")]
    public bool NonPersonalizedAds { get; set; }
    [JsonProperty("events")]
    public List<Event> Events { get; set; }
}
public class Event
{
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("params")]
    public Dictionary<string, object> Parameters { get; set; }
}
  • Related