0

I've got several JsonConverters and want to refactor some common validation code out into a set of extension methods.

The below works as I want for string values, but how would be best to extend the coverage of ReadAndCheckProperty() to support other types Utf8JsonReader supports reading?

using System.Text.Json;

namespace MyExtensions {
  public static class Utf8JsonReaderExtensions {
    public static void EnsureLastTokenWas(ref this Utf8JsonReader reader, JsonTokenType tokenType) {
       if (reader.TokenType != tokenType) {
         throw new JsonException();
       }
     }

    public static void EnsureNextTokenIs(ref this Utf8JsonReader reader, JsonTokenType tokenType) {
      if (!reader.Read() || reader.TokenType != tokenType) {
        throw new JsonException();
      }
    }

    // check and read a property with a string value
    public static string ReadAndCheckProperty(ref this Utf8JsonReader reader, string propertyName) {
      reader.ReadAndCheckPropertyNameAndType(propertyName, JsonTokenType.String);
      return reader.GetString();
    }

    private static void ReadAndCheckPropertyNameAndType(ref this Utf8JsonReader reader, string propertyName, JsonTokenType tokenType) {
      if (!reader.Read() || reader.TokenType != JsonTokenType.PropertyName || reader.GetString() != propertyName) {
        throw new JsonException();
      }
      if (!reader.Read() || reader.TokenType != tokenType) {
        throw new JsonException();
      }
    }
  }
}

I thought I'd do this along the lines of adding overloads of ReadAndCheckProperty() like this

// check and read a property with a 32 bit number value
public static int ReadAndCheckProperty(ref this Utf8JsonReader reader, string propertyName) {
  reader.ReadAndCheckPropertyNameAndType(propertyName, JsonTokenType.Number);
  return reader.GetInt32();
}

But that won't work as-is as the method parameters would be the same. If this is the right way to tackle this (it feels like I'll end up with lots of little methods, which doesn't feel great but not too bad), how would it be best to distinguish them?

Thanks!

bemo
  • 400
  • 3
  • 11
  • 1
    Overload resolution does not consider return types. You'd have to give the methods different names. Alternatively, make `ReadAndCheckProperty` generic and use `JsonSerializer.Deserialize(reader)` instead of `reader.GetWhatever()`. Then you can do `reader.ReadAndCheckProperty(propertyName)`, `reader.ReadAndCheckProperty(propertyName)`, and so on. – Jeff Feb 02 '21 at 18:22
  • Thanks @Jeff, I'd tried generics earlier like `T ReadAndCheckProperty(...)` with a if-else ladder of a few supported types, but I hit a stumbling block when making the return, e.g. I can't cast the return of `reader.GetString()` to a `T` – bemo Feb 02 '21 at 21:42
  • I meant that you can get rid of `reader.GetX()` and replace it with `JsonSerializer.Deserialize(reader)`. So: `static int ReadAndCheckProperty(ref this Utf8JsonReader reader, string propertyName) { reader.ReadAndCheckPropertyNameAndType(...); return JsonSerializer.Deserialize(reader); }` – Jeff Feb 02 '21 at 21:51

0 Answers0