Suggestion: make built-in structs more JSON-friendly?

Hi,
Not sure who maintains MG at the moment but I wanted to discuss improving structs serialization here before doing a PR that might just get rejected, since it might be considered a breaking change.

So here’s the deal - MG base structs are not serialization friendly. And that’s a huge bummer.

For example, if we choose the built-in C# JSON serializer with the following class:

class MyClass
{
    public Vector2 SomeVector { get; set; } = new Vector2(42, 11);
    public Rectangle SomeRect { get; set; } = new Rectangle(12, 44, 111, 334);
    public Color SomeColor { get; set; } = Color.Red;
}

The result will be this:

{
    "SomeVector": {},
    "SomeRect": {
        "Left": 12,
        "Right": 123,
        "Top": 44,
        "Bottom": 378,
        "IsEmpty": false,
        "Location": {},
        "Size": {},
        "Center": {}
    },
    "SomeColor": {
        "B": 0,
        "G": 0,
        "R": 255,
        "A": 255,
        "PackedValue": 4278190335
    }
}

As you can see this have several issues:

  • Vectors don’t serialize at all.
  • Rectangles serialize lots of useless junk.
  • Colors - could argue it shouldn’t serialize PackedValue.

IMO the vectors case is quite simple - they don’t serialize at all, which is a shame.
The redundant fields in Rectangle and Color are more an open question - on one hand they are useful for deserialization, ie its good that I can either deserialize R, G, B keys, or a single PackedValue key instead. However I’m not sure its smart to also Serialize them all by default.

Anyway what’s your opinion on the subject? This all can be fixed with some attributes but if I do a PR, will it be accepted?

Let’s discuss this topic, and also I’d love to hear alternative solutions if any of you also use JSON files.

PS I know there’s also the option of XML content files that serialize alright, but I prefer to avoid those as they add noise and are less user friendly.

Thanks!

Hello!

I am actually curious on this matter. I usually write my own serializers, but truth be said, I have never tried to serialize Vector2 before. How are you serializing?

What I currently do when not using the content XML files (which require additional dll to include by the content manager which is annoying), is to define my own clones of MonoGame basic structs with converters.

For example:

public class _Vector2
{
   public float X {get; set;}
   public float Y {get; set;}
   public Vector2 ToMg => new Vector2(X, Y);
}

Not the cleanest or most efficient way, but it serialize and deserialize nicely and good enough for now But ofc I’d prefer to avoid it and use MG base objects :slight_smile:

Yeah, I use content manager next to zero. I actually write my own font handler that takes a bitmap sprite sheet and all that, so I may be too old school for this topic. But I assume you use the serialization to save a state somehere that you’d pick up later, right? If so, what mechanism you use to populate your classes with a saved state?

1 Like

Use it both for saving mechanism, and to store game data files in a way that players can easily temper with.

I feel you with the content manager. I’m less fond of the concept. Tons of respect to the people working on it, but I prefer to load my resources from raw files and path, even if it means less built-in compression. I even made some class long time ago to load most of the built-in assets without the content manager, I think there’s an old post about it somewhere in this forum. But as you said maybe we’re just old school :smiley:

Yeah, the way I look at MonoGame is this: It provides the basics but then I take over. And I am used to taking over heavily. For instance, I wrote my own class that takes resources from a .zip file that can also be obfuscated. This is why I was curious why would you want to design something generic for something that “in my view” should be very developer-specific. Why not write your own implementation? It would be also very safe for you along the way.

Same force that drives humanity to its greatness: laziness.
I don’t want to invest in serialization code!

Btw regarding this part:

I wrote my own class that takes resources from a .zip file that can also be obfuscated

I don’t know if you plan to release on steam, but if you do you should know that if your compression completely changes the output for any small change, as these things often do, it will mess up the steam updating system and will update everything every time you change even a tiny resource.

Fair enough, but right now, since you decided to go on the root folder of MonoGame forum and point to this, I think sincerely you are investing a lot of effort, to which I can only applaud to, but it goes against this statement of yours.

Yes, very aware. No worries, I just gave a simplistic example. Will not give out other details. :wink:

Sorry if I’m missing something, but why don’t you use Json.NET for this?
See here: Serializing and Deserializing JSON

Using your example class above…

class MyClass
{
    public Vector2 SomeVector { get; set; } = new Vector2(42, 11);
    public Rectangle SomeRect { get; set; } = new Rectangle(12, 44, 111, 334);
    public Color SomeColor { get; set; } = Color.Red;
}

The following code…

MyClass testClass = new MyClass();
Console.WriteLine(JsonConvert.SerializeObject(testClass, Formatting.Indented));

Generates the following output…

{
  "SomeVector": "42, 11",
  "SomeRect": {
    "X": 12,
    "Y": 44,
    "Width": 111,
    "Height": 334
  },
  "SomeColor": {
    "B": 0,
    "G": 0,
    "R": 255,
    "A": 255
  }
}

As far as I know Json.NET works cross platform. I used it successfully on Android, at least.

1 Like