简体   繁体   中英

How to programatically edit a swagger yaml file in java to add a request parameter to a REST end point?

I have a yaml file given by a third party library containing 5000+ lines.

That yaml file needs to read,then a query parameter "status" needs to be added to
a REST end point with the path for non methods.的 REST 端点,用于非方法。

Edit 1: I don't have a class file or a POJO. It's a swagger yaml.

I have looked at the SwaggerParser, but I see a lot of code snippets for reading the yaml file but not to add to it.

As you correctly noted, you can use Swagger Parser to modify OpenAPI/Swagger definitions.

Note that (as of July 2019) there are 2 versions of Swagger Parser, and they use slightly different package names and class names:

  • Swagger Parser 2.0 ( io.swagger.v3.parser.OpenAPIV3Parser ) – reads Swagger 1.x, Swagger 2.0 and OpenAPI 3.0 formats and writes OpenAPI 3.0 .

  • Swagger Parser 1.x ( io.swagger.parser.SwaggerParser ) – reads Swagger 1.x and Swagger 2.0 formats and writes Swagger 2.0 .

Since your definition is Swagger 2.0, I assume you want to keep it as such, so you need Swagger Parser 1.x .


Here's how you would add a new parameter:

import io.swagger.parser.SwaggerParser;
import io.swagger.models.Swagger;
import io.swagger.models.Operation;
import io.swagger.models.HttpMethod;
import io.swagger.models.parameters.QueryParameter;
import io.swagger.util.Yaml;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.util.Map;
...

Swagger swagger = new SwaggerParser().read("https://petstore.swagger.io/v2/swagger.json");

// Configure the "status" query parameter
QueryParameter status = new QueryParameter();
status.setName("status");
status.setType("string");
// You can also setDescription, setRequired, setExample, etc. as needed

// Get all HTTP methods for the "/pet/{petId}" path
Map<HttpMethod, Operation> operations = swagger.getPaths().get("/pet/{petId}").getOperationMap();

// Add the "status" parameter to non-GET methods only
for (Map.Entry<HttpMethod, Operation> op : operations.entrySet()){
    if (op.getKey() != HttpMethod.GET) {
        // TODO: Check if this operation already has
        // a query parameter named "status"

        op.getValue().addParameter(status);
    }
}

// Save the new file
try {
    // (Optional) Configure YAML formatter
    YAMLFactory factory = (YAMLFactory) Yaml.mapper().getFactory();
    factory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
        .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
        .enable(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS);

    String yaml = Yaml.pretty().writeValueAsString(swagger);
    FileUtils.writeStringToFile(new File("C:\\Work\\petstore-modified.yaml"), yaml);
}
catch (Exception e) {
    e.printStackTrace();
}

This example assumes all paths and parameters are defined inline (no $refs). Depending on how your actual API definition is structured, you may need to update the code to properly handle:

  • paths that are $ref'erenced

    paths: /something: $ref: './pathitems/something.yaml'
  • existing path-level parameters with the same name as the parameter you want to add

    paths: /something: parameters: - in: query name: status type: string
  • existing parameters with the same name that are $ref'erenced rather than defined inline

    paths: /something: parameters: - $ref: '#/definitions/statusQueryParam' /something2: post: parameters: - $ref: '#/definitions/statusQueryParam' parameters: statusQueryParam: in: query name: status type: string
  • etc.

I would try the Jackson libraries to play around with yaml files as they have both read and write api's (usage is just like json).

// Create an ObjectMapper mapper for YAML
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

Map config = mapper.readValue(new File("src/main/resources/orderInput.yaml"), Map.class);

//modify your class as needed here
((Map) config.get("rest")).put("your/changes/here")

// Write object as YAML file
mapper.writeValue(new File("/path/to/yaml/file"), yourClass);
Alternatively you can write your object as a string:

// Write object as YAML string
String yaml = mapper.writeValueAsString(example);  

Refer to the below thread fro more info.
Writing Java object instance to YAML using Jackson

Edit: based on the question edit, I am modifying the answer a bit, instead of unwrapping the file into a pojo/class, I would use a Map to cast it to , make necessary edits to it and the write it back. Another way of doing it in a safer way is to do a objectMapper.readTree() which returns a JsonNode, modify the node, and then push it back

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM