Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for jsonpatch #199

Closed
JanEggers opened this issue Oct 19, 2016 · 7 comments
Closed

Support for jsonpatch #199

JanEggers opened this issue Oct 19, 2016 · 7 comments

Comments

@JanEggers
Copy link

Hi

im triing to get my patch operations working but the generated swagger is/seems wrong.

i have seen domaindrivendev/Swashbuckle.WebApi#595 but that is related to asp.net classic

in asp.net core JsonPatch is part of the framework but the generated swagger.json is wrong:

i get:

"JsonPatchDocument[T]": {
"type": "object",
"properties": {
"operations": {
"type": "array",
"items": { "$ref": "#/definitions/Operation[T]" },
"readOnly": true
}
}
}

but it should be:

"JsonPatchDocument": {
"type": "array",
"items": { "$ref": "#/definitions/Operation" },
}
}

can someone please point me in the right direction?

@JanEggers
Copy link
Author

JanEggers commented Oct 20, 2016

i found a workaround:

i changed the methodsignature from JsonPatchDocument to Operation[], that way swagger is generated correctly.

i dont like this approach because i need JsonPatchDocument to apply the patch. Its constructor contains IContractResolver as parameter that now needs to be obtained somehow.

and its simply not the way its ment to be according to:
http://benfoster.io/blog/aspnet-core-json-patch-partial-api-updates

@RehanSaeed
Copy link
Contributor

I wrote the following ISchemaFilter which fixes the example JSON for any parameters which are JsonPatchDocument<T>. However, Ahoy is wrapping my example with { "operations": [ MYCONTENT ] }. @JanEggers Did you figure this out.

public class JsonPatchDocumentSchemaFilter : ISchemaFilter
{
    public void Apply(Schema model, SchemaFilterContext context)
    {
        if ((context.SystemType.GenericTypeArguments.Length > 0) &&
            (context.SystemType.GetGenericTypeDefinition() == typeof(List<>)) &&
            (context.SystemType.GenericTypeArguments.First().GetGenericTypeDefinition() ==
            typeof(Microsoft.AspNetCore.JsonPatch.Operations.Operation<>)))
        {
            model.Default = new List<Microsoft.AspNetCore.JsonPatch.Operations.Operation>()
            {
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "replace",
                    path = "/property",
                    value = "New Value"
                },
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "remove",
                    path = "/property"
                },
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "replace",
                    path = "/arrayProperty/0",
                    value = "New Array Item"
                },
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "add",
                    path = "/arrayProperty/-",
                    value = "New Array Item"
                },
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "remove",
                    path = "/arrayProperty/0"
                },
                new Microsoft.AspNetCore.JsonPatch.Operations.Operation()
                {
                    op = "move",
                    from = "/arrayProperty/0",
                    path = "/arrayProperty/2"
                },
            };
        }
    }
}

@JanEggers
Copy link
Author

in short no i didnt figure it out.

thats why i changed the contract of my methods to be operation[].

but there must be some kind of serialization feature that makes shure the document is deserialized correctly but the swagger is wrong

@RehanSaeed
Copy link
Contributor

This does the trick:

namespace Bridge.FeatureToggle.Api.ViewModelSchemaFilters
{
    using Microsoft.AspNetCore.JsonPatch;
    using Swashbuckle.Swagger.Model;
    using Swashbuckle.SwaggerGen.Generator;
    using Operation = Microsoft.AspNetCore.JsonPatch.Operations.Operation;

    public class JsonPatchDocumentSchemaFilter : ISchemaFilter
    {
        public void Apply(Schema model, SchemaFilterContext context)
        {
            if (context.SystemType.GenericTypeArguments.Length > 0 &&
                context.SystemType.GetGenericTypeDefinition() == typeof(JsonPatchDocument<>))
            {
                model.Default = GetExample();
                model.ExternalDocs = new ExternalDocs()
                {
                    Description = "JSON Patch Documentation",
                    Url = "http://jsonpatch.com/"
                };
            }
        }

        private static Operation[] GetExample()
        {
            return new Operation[]
            {
                new Operation()
                {
                    op = "replace",
                    path = "/property",
                    value = "New Value"
                },
                new Operation()
                {
                    op = "add",
                    path = "/property",
                    value = "New Value"
                },
                new Operation()
                {
                    op = "remove",
                    path = "/property"
                },
                new Operation()
                {
                    op = "copy",
                    from = "/fromProperty",
                    path = "/toProperty"
                },
                new Operation()
                {
                    op = "move",
                    from = "/fromProperty",
                    path = "/toProperty"
                },
                new Operation()
                {
                    op = "test",
                    path = "/property",
                    value = "Has Value"
                },
                new Operation()
                {
                    op = "replace",
                    path = "/arrayProperty/0",
                    value = "Replace First Array Item"
                },
                new Operation()
                {
                    op = "replace",
                    path = "/arrayProperty/-",
                    value = "Replace Last Array Item"
                }
            };
        }
    }
}

@JanEggers
Copy link
Author

that doesnt do anything it just fixed the example data but the type in the swagger.json remains the same.

@domaindrivendev can u please elaborate why the type isnt detected correctly

@Eilon
Copy link

Eilon commented Oct 27, 2016

Hi folks, we logged aspnet/Mvc#5464 for MVC to describe this case more accurately in MVC's ApiExplorer. But for the meantime the workarounds here should be fine. Thanks!

@JanEggers
Copy link
Author

okay if the error is in mvc api explorer ill close this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants