kevinswiber / siren

Structured Interface for Representing Entities, super-rad hypermedia
MIT License
1.3k stars 71 forks source link

Properties title #77

Open amoskopp opened 7 years ago

amoskopp commented 7 years ago

This introduces human-readable titles for entity properties in a backwards-compatible way. Among other advantages, properties with objects as values would enable clients to display labels translated to the HTTP Accept-Language.

apsoto commented 7 years ago

I don't see how this is backwards compatible. A client has to check if a property is an object, but existing clients won't.

amoskopp commented 7 years ago

@apsoto can you tell me what part of the existing specification or JSON schema specifically disallows using non-strings as values? As far as I know, declaring something as object only implies that keys have to be strings.

apsoto commented 7 years ago

There's isn't anything that disallows non-string values, but existing servers where there are entities with objects as properties this is a breaking change because there was no title or value requirement when they were implemented.

If there was a way for clients/servers to negotiate compatible spec versions then this would be compatible.

amoskopp commented 7 years ago

I understand. This probably means that title and value should not be made mandatory. @kevinswiber what are your thoughts regarding human-readable labels for properties?

kevinswiber commented 7 years ago

The purpose of the properties object is to allow free-form data elements without restriction.

We haven't figured out how to advertise "extensions" yet, but having a title->value constraint in properties would make a good one. I don't see this concept making into the media type specification as-is, given the goal stated above.

amoskopp commented 7 years ago

@kevinswiber what about media type parameters? Like with audio/ogg; codecs=vorbis and audio/ogg; codecs=opus one could advertise the set of extensions used with a specified parameter, like application/siren+json; extensions="properties_title,range_contraints".

martinotten commented 7 years ago

@kevinswiber But wouldn't anything apart from a simple type like an object be actually an entity? I think as soon as you got a nested structure you can and should give it a name.

apsoto commented 7 years ago

@martinotten I've found it useful to have the flexibility to put an array or other simple objects in properties in some cases. If I had to turn those into entities it would be rather burdensome.

smizell commented 7 years ago

I've explore this before on how to annotate data in data that maybe nested—and it's quite difficult. Here are the options I've found.

Provide annotations in a separate flat object

This would use a special object for defining semantics apart from the actual values, then optionally map those to the properties in the object. I tried this approach here though it's old and wildly incomplete :)

{
    "class": ["my-entity"],
    "semantics": [
        {
            "title": "Bar",
            "property": "foo.bar"
        }
    ],
    "properties": {
        "foo": {
            "bar": "baz"
        }
    }
}

This is a little more backwards compatible.

Embed annotations with a reserved property

Allow for metadata around properties to be added into a reserved object. Whereas the example above was flat and probably done at the root of an entity, this would be nested inside the property object. JSON-LD does some of this with it's prefixed properties and @context.

{
    "class": ["my-entity"],
    "properties": {
        "_meta": {
            "foo": {
                "title": "Foo"
            }
        },
        "foo": "bar"
    }
}

We also put together a similar proposal for a more complex implementation for annotating JSON in what we called embedded annotations.

This is backwards compatible only if clients are instructed to ignore properties it does not know about AND they haven't used _meta.

Allow for expanding values

This is the route this PR takes. The downsides are that you you end up with a magical recursion for handling annotations, and it gets very complicated as you get more nesting in the properties object. Additionally, it also requires reserved fields because there is no way for a client to know if the presence of title and value means it's a title annotating a value, or if it's actual data.

Full on XML

Don't do this with Siren, just use XML :) Basically, if you wanted to, you mimic how XML works. Again, don't do this, however, the current PR is a baby step toward this direction.

{
    "nodeType": "string",
    "attributes": {
        "title": "Foo"
    },
    "value": "foo"
}
martinotten commented 7 years ago

@apsoto Why is that bothersome? This entity wouldn't need its own URI, would it? So moving it to an entity would just mean that you express it in a different structure. It would also have the advantage that you would also define a class you can reuse in another context, like an address.

apsoto commented 7 years ago

@martinotten

WRT turning complex property structures into entities is burdensome in that it requires more coding. Likely it's a side effect of the way we serialize our Siren responses. Adding properties are simple one line changes. Adding new entities are typically whole new Classes (as in Java or Ruby classes)

Also, I personally do in fact model entities as an uniquely addressable object (URI). If an entity doesn't have a URI then it's a design smell that it maybe shouldn't really be an entity.