private static void setParametersToNode(ObjectNode root,
                                            Iterable<Entry<String, String>> parameters,
                                            TranscodingSpec spec, boolean pathVariables) {
        for (Map.Entry<String, String> entry : parameters) {
            Field field = null;
            if (pathVariables) {
                // The original field name should be used for the path variable
                // Syntax: Variable = "{" FieldPath [ "=" Segments ] "}" ;
                field = spec.originalFields.get(entry.getKey());
            } else {
                // A query parameter can be matched with one of an original field name, a camel case name or
                // a json name depending on the `HttpJsonTranscodingOptions`.
                for (Map<String, Field> mappingFields : spec.queryMappingFields) {
                    field = mappingFields.get(entry.getKey());
                    if (field != null) {
                        break;
                    }
                }
            }
            if (field == null) {
                // Ignore unknown parameters.
                continue;
            }

            if (field.javaType == JavaType.MESSAGE) {
                throw new IllegalArgumentException(
                        "Unsupported message type: " + field.descriptor.getFullName());
            }

            ObjectNode currentNode = root;
            for (String parentName : field.parentNames) {
                final JsonNode node = currentNode.get(parentName);
                if (node != null) {
                    // It should be an ObjectNode but it may not if a user sent a wrong JSON document
                    // in the HTTP body with HTTP POST, PUT, PATCH or DELETE methods.
                    checkArgument(node.isObject(), "Invalid request body (must be a JSON object)");
                    currentNode = (ObjectNode) node;
                } else {
                    currentNode = currentNode.putObject(parentName);
                }
            }

            // If the field has a 'repeated' label, we should treat it as a JSON array node.
            if (field.isRepeated()) {
                final ArrayNode arrayNode;
                final JsonNode node = currentNode.get(field.name());
                if (node != null) {
                    // It should be an ArrayNode but it may not if a user sent a wrong JSON document
                    // in the HTTP body with HTTP POST, PUT, PATCH or DELETE methods.
                    checkArgument(node.isArray(), "Invalid request body (must be a JSON array)");
                    arrayNode = (ArrayNode) node;
                } else {
                    arrayNode = currentNode.putArray(field.name());
                }
                // If a request has multiple values for a query parameter like 'param=foo&param=bar&param=baz',
                // the following JSON would be generated.
                // { "param": ["foo", "bar", "baz"] }
                setValueToArrayNode(arrayNode, field, entry.getValue());
            } else {
                setValueToObjectNode(currentNode, field, entry.getValue());
            }
        }
    }
Converts the HTTP request to gRPC JSON with the {@link TranscodingSpec}.
grpc/src/main/java/com/linecorp/armeria/server/grpc/HttpJsonTranscodingService.java