简体   繁体   中英

How to generate JSON example values for class, just like Swagger does for example response?

I'm using Swagger with my ASP.NET Core application and for a HTTP POST endpoint returning Blog model:

[HttpPost]
[ProducesResponseType(typeof(Blog), StatusCodes.Status200OK)]
public IActionResult AddBlog([FromBody] string name)
{
    // Code removed for brevity...
    return Ok(newBlog);
}

Blog:

public Blog
{
    public int Id { get; set; }

    public string Name { get; set; }
}

Swagger in its UI will show example response for that endpoint:

{
  "Id": 0,
  "Name": "string"
}

What I'd like to do is to generate such example values in JSON for type of class I provide and where I need it, which is somewhere else in my application like:

var json = exampleValuesGenerator.Generate(typeof(Blog));

Is this possible?

Yes, it's possible to generate such example values for responses and for POST request. For Get requests, it's difficult, see my question here: SwashBuckle Swagger-UI Example Request for HTTP GET Method with FromQuery Attribute

Have a look at the NuGet package Swashbuckle.AspNetCore.Filters :

You can define an example response such as this:

public class BlogExample : IExamplesProvider<Blog>
{
    public Blog GetExamples()
    {
        return new Blog()
        {
            Id = 123,
            Name = "John Smith"
        };
    }
}

SwaggerUI will then show these values instead of the empty default values.

Closest I've come to the desired generator is by using a library NJsonSchema . Thanks to @Helen for giving me valuable directions to Json Schema. Usage example below:

public string Generate(Type type)
{
    return JsonSchema
        .FromType(type)
        .ToSampleJson()
        .ToString();
}

It isn't perfect though. For example, for model defined as follows:

public class User
{
    public string String { get; set; }
    public int Int { get; set; }
    public double Double { get; set; }
    public float Float { get; set; }
    public short Short { get; set; }
    public byte Byte { get; set; }
    public long Long { get; set; }
    public decimal Decimal { get; set; }
    public DateTime DateTime { get; set; }
    public TimeSpan TimeSpan { get; set; }
    public bool Bool { get; set; }
    public BindingFlags Enum2 { get; set; }
    public Blog NestedObject { get; set; }
    public Blog[] ArrayOfObjects { get; set; }
    public int[] ArrayOfValues { get; set; }
}

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

it generates a sample JSON:

{
  "String": "String",
  "Int": 0,
  "Double": 0,
  "Float": 0,
  "Short": 0,
  "Byte": 0,
  "Long": 0,
  "Decimal": 0,
  "DateTime": "2020-08-02T19:43:59.8759099+00:00",
  "TimeSpan": "TimeSpan",
  "Bool": false,
  "Enum2": 0,
  "NestedObject": null,
  "ArrayOfObjects": [
    {
      "Id": 0,
      "Name": "Name"
    }
  ],
  "ArrayOfValues": [
    0
  ]
}

Sadly NestedObject property is null when it shouldn't be and floating point types should have example value suggesting they are indeed floating type, not just 0 suggesting that they are of integer type. So yeah, it could be improved. But it's definitely better than nothing!

NJsonSchema is fine to generate the sample json for a CLR type:

var sampleJson = JsonSchema.FromType(typeof(Foo)).ToSampleJson().ToString();

Hoverer,if Foo has nested complex type as properties,you have to add additional attribute such as [Required] to make things work.

As a result,i prefer to combine AutoFixture with NJsonSchema to generate the sample json,here is the example:

[Fact]
public void Test1()
{
  var sampleJson = JsonConvert.SerializeObject(new Fixture().Create<Foo>());
  var str = JsonSchema.FromSampleJson(sampleJson).ToSampleJson();
  File.WriteAllText(Path.Combine(Path.GetTempPath(),Path.GetTempFileName()),str.ToString());
}

You can use any JSON library and serialise an empty object.

Using newtonsoft JSON

var json = JsonConvert.SerializeObject(new Blog());

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