fuhrysteve / marshmallow-jsonschema

JSON Schema Draft v7 (http://json-schema.org/) formatting with marshmallow
MIT License
209 stars 72 forks source link

Ability to modify JSON schema property name #83

Closed yeralin closed 5 years ago

yeralin commented 5 years ago

Hi,

I have a problem with marshmallow-jsonschema where during the translation it uses field names rather that schema attributes.

For example, I have a following schema:

class ExampleSchema(Schema):
    api_token = String(attribute='api-token', required=True,
                       description='API token.')

If I run JSONSchema().dump(ExampleSchema()).data, it will translate to:

{
    "$ref": "#/definitions/LoginTokenRequestSchema",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "ExampleSchema": {
            "additionalProperties": false,
            "properties": {
                "api_token": {
                    "description": "API token.",
                    "title": "api-token",
                    "type": "string"
                }
            },
            "required": [
                "api_token"
            ],
            "type": "object"
        }
    }
}

As you can see, it used the field name (ExampleSchema.api_token) from the schema instead of its attribute (api-token). attribute='api-token' was used for title in the resulting JSON schema.

Originally in the marshmallow core, attribute parameter is utilized for marshaling: https://marshmallow.readthedocs.io/en/2.x-line/quickstart.html#specifying-attribute-names

In my case, I'm just trying to follow PEP8 having lower_case_with_underscores variable names in the python code, but then in the resulting JSON schema I would want to follow camelCase. I was hoping to achieve that specifying attribute parameter.

Is there some kinda parameter I could pass to JSONSchema to pick schema's attribute instead?

fuhrysteve commented 5 years ago

Interesting.. I'm curious what your the use case is.. In other words: why do you care how the field name is spelled as long as it's unique, descriptive, and consistent?

yeralin commented 5 years ago

In my case, I essentially have JSON payloads that contain an api-token field:

{
    'api-token': 'someToken',
     ...
}

I use this ExampleSchema to deserialize these payloads. Now, all I am trying to do is to generate JSON Schema out of the python marshmallow classes that would conform to the original input payloads.

I hope it makes sense? 😅

yeralin commented 5 years ago

Ok, I looked deeper into the issue. The actual entry key name is set here: https://github.com/fuhrysteve/marshmallow-jsonschema/blob/b29a8afd11d8eb7f0d34a8ad7de72cf102105a89/marshmallow_jsonschema/base.py#L112

I looked at the impl of marshmallow.fields.field class hoping to find a way to modify field.name, but I only found this: https://github.com/marshmallow-code/marshmallow/blob/e0163744069de0eacc0e70fbc0d8d5937bab753a/src/marshmallow/fields.py#L335-L343

Basically, it is not possible to change field.name from a client's side. Then, the only way to change the key of a resulting JSON schema is to do that on marshmallow-jsonschema side...

How about looking for name extra metadata argument (since schema's attribute param is already reserved for JSON schema's title field) under a field like:

class ExampleSchema(Schema):
    api_token = String(name='api-token', required=True,
                       description='API token.')

Then, on marshmallow-jsonschema side doing something like:

properties[field.metadata.get('name') or field.name] = schema

which will result in:

"properties": {
    "api-token": {
        "description": "API token.",
         ...
    }
},