Short answer: Big, big +1 to this idea.
I think this is important. While I think that having separate objects for phones, emails, etc. attached to other objects directly has worked for HSDS in the past; it’s exactly these types of use cases that the concept of something like a contact_point or contact_method covers.
This is done in other Standards as well, the best example being Open Contracting:
I think there’s two things to consider here:
- What can we do in the short-medium term, within the context of a MINOR upgrade?
- How should we re-model HSDS to cover these cases when it does come time for a MAJOR upgrade?
In terms of doing this in a MINOR upgrade; I think that’s fairly straightforward:
- implement a
contact_method(orcontact_point, or whatever) schema. - ensure that this
contact_methodschema references existing HSDS schemas where possible e.g.contact_method.phoneshould be an instance ofphone. - add a
contact_method.weightorcontact_method.priorityproperty, with an appropriate description. This makes querying for this very straightforward. - add
contact_methodsas a property on relevant schemas - mark older properties such as
service.phonesas deprecated in the schema. This means they’re not removed, which preserves backwards compatability but encourages people to use the newer properties. Deprecating properties is a feature of JSON Schema 2020-12, so we can take advantage of this here. I believe most general-purpose validators which speak JSON Schema 2020-12 should pick up on this and issue warnings (not errors!) to data which uses deprecated fields.
I support this idea whole-heartedly, but here’s some direct answers to your questions:
- What are other methods we could use to solve ranking/prioritization among contact methods?
Without a contact_method schema, one alternate way to do this would be to create an object or property which models the weighting specifically and references the id fields of the other objects. I think this would be quite clunky, and still involves adding a new object or property to all the schemas.
Another way would be to add a weighting or priority property to the other schemas themselves e.g. phone.weight or phone.priority… but I don’t like this either. A phone or an email with a weight doesn’t make sense by itself, and the weighting/priority might be relational and depend on the context. There might be a case where a particular email object is the top-ranked contact point for one service, but might be second to a separate contact point for another service. Much better to encapsualte these into a contact_method which describes a single contact point for that service/organizatin/location and its priority compared to its neighbours.
- How might we use attributes to solve this problem?
I think there are multiple ways to use attributes here. For me, the most intuitive would be to have the attribute atop the object you’re describing contact points for e.g. service, and use attributes.label to describe that this is a weighting of contact points, and then use attributes.value to describe the actual weighting.
Again, I think this is not preferable to having a contact_point schema, as implementors would need to agree on the label; at which point it’s a case that something like this should just be a feature of the Standard.
- Are there other uses-cases that support or negate this presumed need?
Having a single contact_point encapsulate phone, email, etc. would also allow for cases where e.g. the contact point is “the front desk” or “this named role”, and have different methods of contact for that contact point e.g. “The Front Desk has this email and this phone number”. At the moment, Organizations just have arrays of phone numbers, uris, and an email attached. Having this modelled explicitly as a “Contact Point” adds semantic meaning to these things as grouping different contact methods together.
Of course, one could then say that we have the same issue again now: how do we choose whether to use contact_point.email or contact_point.phone for the front desk, but I think this is less of an issue than ranking the individual contact points themselves as you note in the use case; for cases where this is needed it could be modelled as a separate contact point with its own weighting. If it becomes super important to rank methods within a single contact point, this could also be achieved.