public static Object parse(JsonParser parser) throws IOException {
        var token = parser.currentToken();
        if (token == JsonToken.VALUE_NULL) {
            return null;
        }
        if (token.isScalarValue()) {
            if (token == JsonToken.VALUE_TRUE) {
                return true;
            }
            if (token == JsonToken.VALUE_FALSE) {
                return false;
            }
            if (token == JsonToken.VALUE_STRING) {
                return parser.getText();
            }
            if (token == JsonToken.VALUE_NUMBER_INT) {
                return parser.getBigIntegerValue();
            }
            if (token == JsonToken.VALUE_NUMBER_FLOAT) {
                return parser.getDoubleValue();
            }
            throw new JsonParseException(parser, "Expecting {VALUE_TRUE, VALUE_FALSE, VALUE_STRING, VALUE_NUMBER_INT, VALUE_NUMBER_FLOAT} token, got " + token);
        }
        if (token == JsonToken.START_OBJECT) {
            var object = new HashMap<String, Object>();
            String fieldName;
            while ((fieldName = parser.nextFieldName()) != null) {
                parser.nextToken();
                var value = parse(parser);
                object.put(fieldName, value);
            }
            return object;
        }
        if (token == JsonToken.START_ARRAY) {
            var object = new ArrayList<>();
            while ((token = parser.nextToken()) != JsonToken.END_ARRAY) {
                var value = parse(parser);
                object.add(value);
            }
            return object;
        }
        throw new JsonParseException(parser, "Unexpected token " + token);
    }
@Test
    void readNestedMap() throws IOException {
        //language=json
        var json = """
            {
              "template": {
                "data": {
                  "url": "https://tinkoff.ru",
                  "number": 1
                }
              }
            }
            """;

        try (var parser = JsonCommonModule.JSON_FACTORY.createParser(json)) {
            parser.nextToken();
            var parseResult = JsonObjectCodec.parse(parser);

            Assertions.assertThat(parseResult)
                .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class))
                .hasSize(1)
                .containsKey("template")
                .extractingByKey("template")
                .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class))
                .hasSize(1)
                .containsKey("data")
                .extractingByKey("data")
                .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class))
                .hasSize(2)
                .containsEntry("url", "https://tinkoff.ru")
                .containsEntry("number", BigInteger.ONE);
        }
    }