0

I am trying to write a function that handles empty values for the datatype Byte.

The reader is reading in a JSON string and serializing to my models.

One of the models has a Byte property.

If the reader encounters a blank or empty string for a Byte, then it should convert it to Null.

But whenever the function is used, I get this error:

System.InvalidOperationException: 'Cannot get the value of a token type 'String' as a number.'

Here is my function:

    public override Byte? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var @byte = reader.GetByte();
        if (string.IsNullOrWhiteSpace(@byte.ToString()))
        {
            return null;
        }
        return Byte.Parse(@byte.ToString());
    }

I am not sure why it is giving me the error or how to fix?

Thanks!

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
SkyeBoniwell
  • 6,345
  • 12
  • 81
  • 185
  • `return Byte.Parse(@byte.ToString());` <-- so return `return @byte;` with more steps? – ProgrammingLlama May 02 '22 at 14:28
  • Also `@byte.ToString()` could never ever be `null` or whitespace. It sounds like your JSON has a `string` value, not a `byte` value. Perhaps you meant to use `reader.GetString()`? – ProgrammingLlama May 02 '22 at 14:30
  • Worse, @byte *might* be null, so the `ToString` will NPE while you're checking for null. – Gus May 02 '22 at 14:32
  • @Gus `@byte` can't ever be `null`. At worse it would be `(byte)0`, but then `((byte)0).ToString()` would yield `"0"`, which isn't `null` or empty. – ProgrammingLlama May 02 '22 at 14:33
  • Interesting; so I suppose if it's asked to `getByte()` on no data, it should throw an exception at that time. There's no try/catch here for that case either – Gus May 02 '22 at 14:38
  • Your method has a typeToConvert parameter you might want to check it. Your reader is currently somewhere in your json so i assume you are guessing on your side that its a byte currently. Or is your json completely consisting only of byte types? – Ralf May 02 '22 at 14:42
  • Seems like a special case of [How to deserialize an empty string to a null value for all `Nullable` value types using System.Text.Json?](https://stackoverflow.com/q/65022834/3744182). – dbc May 02 '22 at 14:44
  • In fact, it might be a duplicate of [How to deserialize an empty string to a null value for all `Nullable` value types using System.Text.Json?](https://stackoverflow.com/q/65022834/3744182), agree? – dbc May 02 '22 at 15:02
  • @Ralf it's an extension method for my models and is used in the `getter` section for byte properties in my models – SkyeBoniwell May 02 '22 at 15:21
  • @dbc so I can treat the byte as a string? I will check out that question link you posted, thanks! – SkyeBoniwell May 02 '22 at 15:22
  • @DiplomacyNotWar I did try `reader.GetString()` and got the same error :( – SkyeBoniwell May 02 '22 at 15:24
  • @SkyeBoniwell - The linked question asks how to map an empty string to a null nullable for all `Nullable` types. You want to do it specifically for `Nullable`, so your question seems like a specific case of that one. That being said, since you know you are deserializing a `Byte` you can replace `return JsonSerializer.Deserialize(ref reader, options)` with `return reader.GetByte()`. The important thing is the `if (reader.TokenType == JsonTokenType.String && reader.ValueTextEquals(Empty)) return null;` check before that. – dbc May 02 '22 at 15:35

2 Answers2

2

It seems that your issue is that you have a string value in from JSON and you're trying to read that as a Byte. Instead, you should try reading it as a string first:

public override Byte? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    string raw = reader.GetString();
    if (string.IsNullOrWhiteSpace(raw)) {
        return null;
    }

    return Byte.Parse(raw);
}

This will do what you want: parse the data as a Byte if it's available or return null if it's empty or missing. As an aside, you should really make use of type-checking to ensure a broader use-case rather than relying on a string-input.

Woody1193
  • 7,252
  • 5
  • 40
  • 90
  • Maybe it's better to use TryParse or wrap in a try catch in order not make to program to terminate in case of the string is not contaning a valid byte numebr – Marco Beninca May 02 '22 at 14:53
  • @MarcoBeninca do you mean use `return Byte.TryParse(raw); ` instead of `return Byte.Parse(raw); ` ? Thanks – SkyeBoniwell May 02 '22 at 15:23
  • You cannot return directly return Byte.TryParse because it return a boolean... you have to pass a byte and test for the result of TryParse and if false return a default value [ByteTryParse](https://learn.microsoft.com/en-us/dotnet/api/system.byte.tryparse?view=net-6.0) – Marco Beninca May 02 '22 at 15:26
  • 1
    When I try that on your example I get this, `System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.` on the line, `string raw = reader.GetString();` – SkyeBoniwell May 02 '22 at 16:47
  • @SkyeBoniwell Them your JSON isn't a string. I don't know what your JSON looks like so I can't give you anymore than that. – Woody1193 May 03 '22 at 00:07
0

While I don't think is an elegant solution or even a proper one, I got this to work by 1) Checking the TokenType and 2) converting it to an int to check for null or empty.

    public override Byte? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var tokenType = reader.TokenType;
        if(tokenType == JsonTokenType.Number)
        {
            var @byte = reader.GetByte();
            var intVal = Convert.ToInt32(@byte);
            if (string.IsNullOrWhiteSpace(intVal.ToString()))
            {
                return null;
            }
            return @byte;
        }
        return null;
    }
SkyeBoniwell
  • 6,345
  • 12
  • 81
  • 185
  • @dbc is this what you meant? – SkyeBoniwell May 02 '22 at 23:24
  • @DiplomacyNotWar , do you think this solution is acceptable? Thanks – SkyeBoniwell May 02 '22 at 23:25
  • You should be able to copy the solution as-is from [How to deserialize an empty string to a null value for all `Nullable` value types using System.Text.Json?](https://stackoverflow.com/a/65025191/3744182), is it not working for you? – dbc May 03 '22 at 00:39
  • @dbc Mine is an extension method for one of my models. That solution seemed really broad and I'm not sure if it would work in .Net 6 using System.Text.Json... – SkyeBoniwell May 03 '22 at 13:28