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

Replace Field.Schema with Field.Validator = schema.Object #77

Open
smyrman opened this Issue Jan 2, 2017 · 18 comments

Comments

Projects
None yet
3 participants
@smyrman
Collaborator

smyrman commented Jan 2, 2017

What are the differences between

s := schema.Schema{
        Fields: schema.Fields{
                "meta": {Schema: subSchema}
        }
}

and

s := schema.Schema{
        Fields: schema.Fields{
                "meta": {Validator: schema.Object{Schema: subSchema}}
        }
}

UPDATE: Updated title to no longer be a question.

Based on the comments below, it would make sense to deprecate Field.Schema in favour of using the Validator for schema.Object. This would leave things more consistent, and avoid ensuring that both formats are handled everywhere by the rest-layer code. E.g. for reference checking, JSON schema conversion and more.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Jan 2, 2017

Owner

Good question. It was add by @yanfali In #24, he can certainly answer.

Owner

rs commented Jan 2, 2017

Good question. It was add by @yanfali In #24, he can certainly answer.

@yanfali

This comment has been minimized.

Show comment
Hide comment
@yanfali

yanfali Jan 2, 2017

Contributor

Primarily use case. I wanted to use a schema in array types. Previously you could only use a type which didn't support schema.

Contributor

yanfali commented Jan 2, 2017

Primarily use case. I wanted to use a schema in array types. Previously you could only use a type which didn't support schema.

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jan 2, 2017

Collaborator

Ah, ok so Field.Schema is the initial support for sub-schemas here. I actually like the Object FieldValidator better than having Field.Schema, as it's both more consistent, and avoids ambiguous meaning like:

 "meta": Field{Validator: schema.String{}, Schema: subSchema}

Would it be sensible to deprecate/remove the Schema attribute from Field - perhaps after tagging a release, as suggested in #65? I assume this could also simplify things internally and avoid handling the same case twice several places? For one I realize we don't handle Field.Schema in the jsonschema package.

Collaborator

smyrman commented Jan 2, 2017

Ah, ok so Field.Schema is the initial support for sub-schemas here. I actually like the Object FieldValidator better than having Field.Schema, as it's both more consistent, and avoids ambiguous meaning like:

 "meta": Field{Validator: schema.String{}, Schema: subSchema}

Would it be sensible to deprecate/remove the Schema attribute from Field - perhaps after tagging a release, as suggested in #65? I assume this could also simplify things internally and avoid handling the same case twice several places? For one I realize we don't handle Field.Schema in the jsonschema package.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Jan 3, 2017

Owner

Yes I think should remove Schema at Field level. It is indeed a breaking change but the project is still not in a stable state so I think it's ok.

For #65 I would rather wait for the Go official way to handle that.

Owner

rs commented Jan 3, 2017

Yes I think should remove Schema at Field level. It is indeed a breaking change but the project is still not in a stable state so I think it's ok.

For #65 I would rather wait for the Go official way to handle that.

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jan 3, 2017

Collaborator

For #65 I would rather wait for the Go official way to handle that.

OK, for the manifest part, but tagging a release in Git (e.g. v0.1.0), is something the team have already recommended us to do, and for end-users, rest-layer would be a lot safer/easier to use if you could rely on a tagged release. Especially when we do breaking changes.

Collaborator

smyrman commented Jan 3, 2017

For #65 I would rather wait for the Go official way to handle that.

OK, for the manifest part, but tagging a release in Git (e.g. v0.1.0), is something the team have already recommended us to do, and for end-users, rest-layer would be a lot safer/easier to use if you could rely on a tagged release. Especially when we do breaking changes.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Jan 3, 2017

Owner

Sure we can tag.

Owner

rs commented Jan 3, 2017

Sure we can tag.

@smyrman smyrman changed the title from Question: Field.Schema v.s. Field.Validator = schema.Object to Replace Field.Schema with Field.Validator = schema.Object Jan 21, 2017

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jan 21, 2017

Collaborator

@rs - updated the title & description.

Collaborator

smyrman commented Jan 21, 2017

@rs - updated the title & description.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Jan 21, 2017

Owner

Are you going to submit a PR for this one?

Owner

rs commented Jan 21, 2017

Are you going to submit a PR for this one?

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jan 22, 2017

Collaborator

I don't know if I can/want to figure out the implications on reference checking... there are some other easier issues I would rather look at, e.g. JSON schema ones...

Collaborator

smyrman commented Jan 22, 2017

I don't know if I can/want to figure out the implications on reference checking... there are some other easier issues I would rather look at, e.g. JSON schema ones...

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jan 22, 2017

Collaborator

At least not know

Collaborator

smyrman commented Jan 22, 2017

At least not know

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Feb 13, 2017

Collaborator

@rs Looking at the definition of Object:

type Object struct {
    Schema *Schema
}

Could we not make Schema implement FieldValidator or at least change the definition to:

type Object Schema
Collaborator

smyrman commented Feb 13, 2017

@rs Looking at the definition of Object:

type Object struct {
    Schema *Schema
}

Could we not make Schema implement FieldValidator or at least change the definition to:

type Object Schema
@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Feb 13, 2017

Collaborator

Maybe it's not so easy btw. At least not without introducing additional breaking changes everywhere...

It would be nice to make the API consistent by removing the Schema attribute, while still avoiding the additional level of nesting/indenting you get by using schema.Object.

Collaborator

smyrman commented Feb 13, 2017

Maybe it's not so easy btw. At least not without introducing additional breaking changes everywhere...

It would be nice to make the API consistent by removing the Schema attribute, while still avoiding the additional level of nesting/indenting you get by using schema.Object.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Feb 13, 2017

Owner

I'm all for introducing breaking changes now that simplify the API rather than later.

Owner

rs commented Feb 13, 2017

I'm all for introducing breaking changes now that simplify the API rather than later.

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Sep 19, 2017

Collaborator

I have done some background thinking on this, and I have a rather radical proposal:

  • Move schema.Fields from Schema to Object, and let the Schema have a Validator field instead. We might want to somehow restrict the validator to support only Object types! However, we should at least be able to hold any of schema.Dict, schema.Object, schema.AllOf and schema.AnyOf (where for the last two types, all entries are within the supported list, recursively checked). This may be hard-coded or based on interfaces.
  • Remove Schema from Field.

Part of the reasoning for this, is that I have a use-case to support something like this at a top level:

s := schema.Schema{
    Description: "My resource",
    Validator: &schema.AllOf{
        &schema.Object{
            Fields: commonFields,
        },
        $schema.AnyOf{
            $schema.Object{Fields: schema.Fields{
                "type":{Validator:&schema.String{Allowed:[]string{"x"}}}},
                "someField":{Validator: validatorX},
            },
            $schema.Object{Fields: schema.Fields{
                "type":{Validator:&schema.String{Allowed:[]string{"y"}}}},
                "someField":{Validator: validatorY},
            }
        }
    }
}

I can do this today via a hook with extra validator rools, but that would fail to generate the right documentation.

Collaborator

smyrman commented Sep 19, 2017

I have done some background thinking on this, and I have a rather radical proposal:

  • Move schema.Fields from Schema to Object, and let the Schema have a Validator field instead. We might want to somehow restrict the validator to support only Object types! However, we should at least be able to hold any of schema.Dict, schema.Object, schema.AllOf and schema.AnyOf (where for the last two types, all entries are within the supported list, recursively checked). This may be hard-coded or based on interfaces.
  • Remove Schema from Field.

Part of the reasoning for this, is that I have a use-case to support something like this at a top level:

s := schema.Schema{
    Description: "My resource",
    Validator: &schema.AllOf{
        &schema.Object{
            Fields: commonFields,
        },
        $schema.AnyOf{
            $schema.Object{Fields: schema.Fields{
                "type":{Validator:&schema.String{Allowed:[]string{"x"}}}},
                "someField":{Validator: validatorX},
            },
            $schema.Object{Fields: schema.Fields{
                "type":{Validator:&schema.String{Allowed:[]string{"y"}}}},
                "someField":{Validator: validatorY},
            }
        }
    }
}

I can do this today via a hook with extra validator rools, but that would fail to generate the right documentation.

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Sep 19, 2017

Collaborator

The error type returned from schema.Object (and any other nested type), will be the existing ErrorMap type.

Collaborator

smyrman commented Sep 19, 2017

The error type returned from schema.Object (and any other nested type), will be the existing ErrorMap type.

@rs

This comment has been minimized.

Show comment
Hide comment
@rs

rs Sep 20, 2017

Owner

Interesting idea. Then instead of Validator shouldn't we rename this field Type?

The root as Object might be enforced in resource. This restriction does not necessarily apply to all use-cases (outside of REST).

Owner

rs commented Sep 20, 2017

Interesting idea. Then instead of Validator shouldn't we rename this field Type?

The root as Object might be enforced in resource. This restriction does not necessarily apply to all use-cases (outside of REST).

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Oct 5, 2017

Collaborator

IN #151, I am proposing to replace ValuesValidator FieldValidator in schema.Dict with Values Fields and later do the same in schema.Array. As already proposed in this issue, schema.Object will also contain a set of fields.

However, for all except schema.Object, keeping the Required property inside the Field definition becomes a bit awkward, or at least we would have to ignore it. JSON Schema have solved this ackwardness by making required a list of strings in the schema. Maybe we should consider to do the same for rest-layer. That would allow us to e.g. specify:

Validator: &schema.Dict{
    Required: []string{"fieldA", "fieldB"},
    KeyValidator: &schema.String{},
    Values: schema.Field{...}
}

And also translate that to JSON Schema:

{
    "type": "object",
    "additionalProperties": {...},
    "required": ["fieldA", "fieldB"]
}

But more importantly, we would not have a unused Field.Required property that would cause confusion when a Field is used within a schema.Array or schema.Dict.

Collaborator

smyrman commented Oct 5, 2017

IN #151, I am proposing to replace ValuesValidator FieldValidator in schema.Dict with Values Fields and later do the same in schema.Array. As already proposed in this issue, schema.Object will also contain a set of fields.

However, for all except schema.Object, keeping the Required property inside the Field definition becomes a bit awkward, or at least we would have to ignore it. JSON Schema have solved this ackwardness by making required a list of strings in the schema. Maybe we should consider to do the same for rest-layer. That would allow us to e.g. specify:

Validator: &schema.Dict{
    Required: []string{"fieldA", "fieldB"},
    KeyValidator: &schema.String{},
    Values: schema.Field{...}
}

And also translate that to JSON Schema:

{
    "type": "object",
    "additionalProperties": {...},
    "required": ["fieldA", "fieldB"]
}

But more importantly, we would not have a unused Field.Required property that would cause confusion when a Field is used within a schema.Array or schema.Dict.

@smyrman

This comment has been minimized.

Show comment
Hide comment
@smyrman

smyrman Jul 26, 2018

Collaborator

I have done some background thinking on this, and I have a rather radical proposal (...)

I want to drag this a little bit further. I think the schema.Field and schema.Schema types could be merged into one:

type Object struct{
    Fields   map[string]Schema
    Required []string
}

type Object struct{
    Fields   map[string]Schema
    Required []string
}

type Schema struct{
    Title       string
    Description string
    ReadOnly    bool
    Type        Validator
}

Or, a variant taking #194 into consideration:

type SchemaBuilder struct{
    Title       string
    Description string
    ReadOnly    bool
    Type        ValidatorBuilder
}

// A compiled schema of some sort...
type Schema interface{
    Title() string
    Description() string
    ReadOnly() bool
    Validate(ctx context.Context, changes, original interface{}) error
    JSONSchema() (map[string]interface{}, error)
}

For now it's just an idea to remember when starting on the actual implementation (some time in the future).

Collaborator

smyrman commented Jul 26, 2018

I have done some background thinking on this, and I have a rather radical proposal (...)

I want to drag this a little bit further. I think the schema.Field and schema.Schema types could be merged into one:

type Object struct{
    Fields   map[string]Schema
    Required []string
}

type Object struct{
    Fields   map[string]Schema
    Required []string
}

type Schema struct{
    Title       string
    Description string
    ReadOnly    bool
    Type        Validator
}

Or, a variant taking #194 into consideration:

type SchemaBuilder struct{
    Title       string
    Description string
    ReadOnly    bool
    Type        ValidatorBuilder
}

// A compiled schema of some sort...
type Schema interface{
    Title() string
    Description() string
    ReadOnly() bool
    Validate(ctx context.Context, changes, original interface{}) error
    JSONSchema() (map[string]interface{}, error)
}

For now it's just an idea to remember when starting on the actual implementation (some time in the future).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment