Config/LinkConverter.cs

JsonConverter for string door link IDs that accepts legacy numeric or null values. It reads a JSON string, number, or null and returns a normalized string, mapping 0 or null to DoorLinks.Unlinked; it writes the string value or Unlinked when null.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace NZombies;

/// <summary>
/// Reads a door flag from JSON whether it was written as a string or a number.
///
/// ⚠️ EXISTS PURELY SO SAVED CONFIGS SURVIVE. Flags were ints with 0 meaning
/// unlinked; they are now names, because "power_room" is what a map author
/// actually thinks and "3" is still a perfectly good name. Without this, every
/// config saved before the change fails to deserialize — System.Text.Json will
/// not put a JSON number into a string property — and the map comes back with
/// no spawns and no barriers, which looks like data loss rather than a format
/// change.
///
/// The old sentinel maps across: 0 becomes blank, which is what unlinked means
/// now.
/// </summary>
public sealed class LinkConverter : JsonConverter<string>
{
	public override string Read( ref Utf8JsonReader reader, Type type, JsonSerializerOptions options )
	{
		switch ( reader.TokenType )
		{
			case JsonTokenType.String:
				return reader.GetString()?.Trim() ?? DoorLinks.Unlinked;

			case JsonTokenType.Number:
				// 0 was "unlinked" in the int form.
				var n = reader.GetInt32();
				return n == 0 ? DoorLinks.Unlinked : n.ToString();

			case JsonTokenType.Null:
				return DoorLinks.Unlinked;

			default:
				reader.Skip();
				return DoorLinks.Unlinked;
		}
	}

	public override void Write( Utf8JsonWriter writer, string value, JsonSerializerOptions options )
		=> writer.WriteStringValue( value ?? DoorLinks.Unlinked );
}