0

I'm currently making a simple config/option system using C# (mainly to replace the PlayerPrefs system in Unity). I orginally designed it similarly to an INI file but decided to take it a step further and use Json to allow infinite nesting of options.

The way the objects are essentially set up are: Option<T> {T Value} and Dictionary<string, Option>

With the previous INI design, it was:

[GRAPHICS]
Resolution=(X=1920, Y=1080)

With Json.NET, it's now:

"Graphics": {
    "Value": {
      "Resolution": {
        "Value": {
          "X": {
            "Value": 1920
          },
          "Y": {
            "Value": 1080
          }
        }
      }
    }
  }

As you can see, it looks really messy and was wondering if there is any way I could make it shorter. For example: remove the "Value" part so it's like:

"Graphics": {
    "Resolution": {
        "X": 1920,
        "Y": 1080,
    }
}

The main goal is to make something that is fairly expandable whiles also being pretty easy to manually edit. Would simply just going to Yaml get me closer to this goal?

public class IOption // (changed to class from interface because Json.Net didn't like deserialising interface)
    {
        public virtual dynamic Value { get; set; }

        public virtual bool SetValue(object value)
        {
            return false;
        }
    }

    public class Option<T> : IOption
    {
        public override dynamic Value { get; set; }

        public Option(T value)
        {
            Value = value;
        }

        public override bool SetValue(object value)
        {
            try
            {
                Value = (T)value;
                return true;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

void SaveToJson()
{
    IDictionary parsableOptions = new Dictionary<string, IOption>();
    Save("SomePath", parsableOptions);
}


public static void Save(string path, object obj)
        {
            var serializer = new Newtonsoft.Json.JsonSerializer();

            using (var sw = new StreamWriter(path))
            using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
            {
                writer.Formatting = Newtonsoft.Json.Formatting.Indented;
                serializer.Serialize(writer, obj);
            }
        }

Update: Using dynamics in place of the IOptions class produced the result I wanted. I also moved to Yaml for it's easier to read aesthetic.
Dynamiquel
  • 105
  • 1
  • 6
  • Hi. Could you please include the actual code that generates the JSON shown? As is, it's difficult to understand precisely what you mean. Please see https://stackoverflow.com/help/minimal-reproducible-example Thanks. – Matt Johnson-Pint Dec 18 '19 at 22:43
  • 1
    Hmm, looks like a duplicate of [Json.NET - Serialize generic type wrapper without property name](https://stackoverflow.com/q/50313978/3744182), agree? Your `Option` looks exactly like `ValueObject` from that question. – dbc Dec 18 '19 at 22:44
  • I decided to just use YAML, it does everything that I wanted to do. That JSON setup got pretty complicated for something I would have thought would be fairly simple. I also realised that I didn't even need to make a Generic object as I can just use dynamics, which to me, do the same job. – Dynamiquel Jan 02 '20 at 01:50

1 Answers1

0

This can be achieved using a custom JsonConverter, which you can read about here.

In your case, you would need to write one for the Option<T> class, so that when the WriteJson method is called, it just outputs the value.

As @dbc mentioned, an answer to this problem can be found here: Json.NET - Serialize generic type wrapper without property name.

JSarwer
  • 313
  • 2
  • 16
  • Thanks for you and everyone else suggesting this answer. I couldn't seem to find anything online. I guess I didn't know the correct terminology. I'll look into it tomorrow. – Dynamiquel Dec 18 '19 at 23:05