0

Background

I have an application that returns an array of Config models from a SQL database. This Config model contains a string property called "CustomConfig" which holds raw JSON specific to each row. The model also contains a JObject property called "CustomConfigObject" which is essentially a deserialized version of the JSON string. This was done in order to keep the SQL Table design simple.

The ultimate point of these rows is to form a large JSON blob used to configure a client experience.

The problem

When all of the post processing has been performed on the Config models, they are then serialised using Newtonsoft.

Upon serialization, the object looks like this -

{
  id: 0,
  name: "Title",
  customConfigObject: {
    items: [...],
    href: "http://...",
    header: "",
    orientation: 0,
    apiKey: 123
  }
}

I am wondering if there is a way of extracting the value of the property during serialization so that the result looks like this instead (notice there is no "customConfigObject") -

{
  id: 0,
  name: "Title",
  items: [...],
  href: "http://...",
  header: "",
  orientation: 0,
  apiKey: 123
}

I have looked into Custom Convertors but I'm not sure it produces the needed outcome.

Any help on this one would be hugely appreciated as out current workaround is to define each possible property of "CustomConfigObject" with a getter to return the sub-property.

Many thanks!

Basic example of the issue -

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        var parent = new Config(){
            Name = "Parent",
            Description = "desc",
            Children = new List<Config>()
        };
        
        var child1 = new Config(){
            Name = "Child",
            Description = "desc",
            CustomConfig = "{ href: 'http://...', header: '...', orientation: 0, apiKey: 123 }"
        };
        
        var child2 = new Config(){
            Name = "Child 2",
            Description = "desc",
            CustomConfig = "{ href: 'http://...', header: 'things', orientation: 1, apiKey: 345 }"
        };
        
        parent.Children.Add(child1);
        parent.Children.Add(child2);
        
        DefaultContractResolver contractResolver = new DefaultContractResolver
            {
                NamingStrategy = new CamelCaseNamingStrategy()
            };

            var json = JsonConvert.SerializeObject(parent, new JsonSerializerSettings
            {
                ContractResolver = contractResolver,
                Formatting = Formatting.Indented,
                NullValueHandling = NullValueHandling.Ignore
            });
        Console.WriteLine(json);
    }
}


public class Config{
    public string Name { get; set; }
    public string Description { get; set; }
    [JsonIgnore]
    public string CustomConfig { get; set; }
    public JObject CustomConfigObject
        {
            get
            {
                if (!string.IsNullOrEmpty(CustomConfig))
                {
                    return JObject.Parse(CustomConfig);
                }

                return null;
            }
        }
    public List<Config> Children { get; set; }
}
Rob Jeffrey
  • 124
  • 12
  • @Crowcoder Using JsonIgnore would remove the entire object, not shift it's contents up a level – Rob Jeffrey Feb 25 '21 at 18:16
  • Yeah, i misunderstood at first – Crowcoder Feb 25 '21 at 18:16
  • You would need to use a [custom `JsonConverter`](https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm) to do that. See e.g. [Can I serialize nested properties to my class in one operation with Json.net?](https://stackoverflow.com/q/30175911/3744182). In fact that may be a duplicate, agree? – dbc Feb 25 '21 at 18:17
  • @Crowcoder It's a head scratcher. To complicate things, these Config objects are nested. So there is infinite complexity to an Config object. – Rob Jeffrey Feb 25 '21 at 18:17
  • @dbc I will give this a try. Not sure if the nested nature of the object will cause issues. Will keep you posted :) – Rob Jeffrey Feb 25 '21 at 18:18
  • 1
    If you need to flatten objects with *infinite complexity* then [Can I serialize nested properties to my class in one operation with Json.net?](https://stackoverflow.com/q/30175911/3744182) may be insufficient. Can you share a [mcve]? Do you need to deserialize, or only serialize? – dbc Feb 25 '21 at 18:19
  • @dbc I have updated the post with a basic example of what our process is outputting. Thanks! – Rob Jeffrey Feb 25 '21 at 19:07
  • 1
    Oh OK I think you can just mark `CustomConfigObject` with [`[JsonExtensionData]`](https://www.newtonsoft.com/json/help/html/DeserializeExtensionData.htm) as shown in [How to serialize a Dictionary as part of its parent object using Json.Net](https://stackoverflow.com/q/14893614/3744182/) and [Can I deserialize to a class and have extra JSON properties go into a JObject on that class?](https://stackoverflow.com/a/27221402/3744182). If you do its properties will be serialized as a part of the parent. In fact this may be a duplicate, agree? – dbc Feb 25 '21 at 19:17
  • 1
    Yes this nails the issue! I actually had the documentation open for that attribute in another tab. The description of the attribute made me think it was for concatenating collections or something. – Rob Jeffrey Feb 25 '21 at 19:28

0 Answers0