Read nested array as whole with Utf8JsonReader

Viewed 1451

I'm trying to parse GeoJSON geometry definition using System.Text.Json's Utf8JsonReader.
My problem is that the coordinates property of the geometry definition might be positioned prior to the definition of the type. coordinates can be

  • a plain array of doubles ([0, 1]) for geometries of type Point,
  • an array of arrays of doubles ([[0,1],[2,3]]) for geometries of type LineString
  • an array of arrays of arrays of doubles ([[[0,0],[10,0],[10,10],[0,0]],[[1,1],[9,9],[1,9],[1,1]]]) for geometries of type Polygon with holes and even
  • an array of the above for geometries of type MultiPolygon.


Thus I am not be able to parse the coordinates property properly if I don't know the type.
Is there a way to read it as whole and parse it later using Utf8JsonReader?

1 Answers

I achieved what I liked to do by using the following function

private ReadOnlySpan<byte> ReadCoordinateData(ref Utf8JsonReader reader)
{
    reader.ReadToken(JsonTokenType.StartArray);
    var res = new MemoryStream();
    res.Write(System.Text.Encoding.UTF8.GetBytes("["), 0, 1);
    int openBrackets = 1;

    bool wasCloseBracket = false;
    bool addComma = false;
    byte bytComma = System.Text.Encoding.UTF8.GetBytes(",")[0];
    while (openBrackets > 0)
    {
        // add a comma to separate arrays
        if (reader.TokenType == JsonTokenType.StartArray)
        {
            if (wasCloseBracket)
                res.WriteByte(bytComma);
            addComma = false;
            openBrackets++;
        }

        if (reader.TokenType == JsonTokenType.Number && addComma)
            res.WriteByte(bytComma);

        byte[] seq = reader.HasValueSequence
            ? reader.ValueSequence.ToArray()
            : reader.ValueSpan.ToArray();
        res.Write(seq, 0, seq.Length);

        addComma = reader.TokenType == JsonTokenType.Number;

        if (reader.TokenType == JsonTokenType.EndArray)
        {
            openBrackets--;
            addComma = false;
            wasCloseBracket = true;
        }
        else
        {
            wasCloseBracket = false;
        }

        if (!reader.Read())
            throw new JsonException();
    }

    return new ReadOnlySpan<byte>(res.ToArray());
}

Related