opengeospatial / sensorthings

The official web site of the OGC SensorThings API standard specification.
135 stars 29 forks source link

Addressing array items #22

Open hylkevds opened 7 years ago

hylkevds commented 7 years ago

As mentioned in the SensorThingsAPI session this week, there are several places where json arrays can appear in properties:

OData does not specify a way to directly address array items. So given for example the Thing:

  {
    "@iot.id": 1,
    "name": "Oven",
    "description": "This thing is an oven.",
    "properties": {
      "owner": {
        "name": "Hylke"
      },
      "elements": [
        "induction",
        "induction",
        "ceramic",
        "ceramic"
      ]
    }
  }

It is possible to request: Thing(1)/properties/owner/name or search using Things?$filter=properties/owner/name eq 'Hylke' But it is not possible to address the type of the second cooking element, or search for Things that have an induction cooking element.

The reason is that OData does not have a data type similar to the ordered array type of JSON.

My proposed solution would be to add an array index element to the URL Conventions: [<nr>] where is the 0-indexed element number (first element is 0), or for any when searching. This would allow one to request: Thing(1)/properties/elements[1] To get the second element type, or search for `Things?$filter=properties/elements[] eq 'induction' To find any Things with any element named 'induction' MultiDatastreams(1)/Observations?$filter=result[2] gt 5` To filter observations in a MultiDatastream on the result of the third ObservedProperty.

I'm not sure about the [*] convention, there might be nicer ways to do it. Maybe with specific functions?

aditisg17 commented 7 years ago

Finding a way to address the array elements is absolutely essential to avoid loss of data and purpose. For eg. the whole purpose of MultiDatastream is lost, if there is no way to access the elements. I would go one step further and request for conditional operators as well on these elements.

Array Index representation appears to be a natural and intuitive choice.

It'll be great if we see the decision on representation soon and subsequently the availability of solution.

Thanks in advance.!!

hylkevds commented 7 years ago

Noticed another potential issue: When fetching Thing(1)/properties/elements the server returns an object with one element that has the name of the requested element, and the value of the requested element:

{
  "elements": [
    "induction",
    "induction",
    "ceramic",
    "ceramic"
  ]
}

What to return when requesting Thing(1)/properties/elements[2]? What to choose for the name of the element in the returned json object? My suggestion would be:

{
  "elements[2]": "ceramic"
}

Nested arrays would be returned as:

Thing(1)/properties/elements[2][3]:
{
  "elements[2][3]": "a string value"
}

Thing(1)/properties/elements[2]/deeper[3]:
{
  "deeper[3]": 12345
}

An other options would be to use just the integer index, as a string. i.e.:

{
  "2": "ceramic"
}
hylkevds commented 5 years ago

I just ran into rfc6901: JavaScript Object Notation (JSON) Pointer (https://tools.ietf.org/html/rfc6901) This rfc defines ways to address entities in json documents. The difference between my proposal above and JSON-Pointer is the way arrays indices are handed. JSON Pointer uses plain numbers, separated with slashes. The example above would be: Thing(1)/properties/elements/2 And nested arrays would be Thing(1)/properties/elements/2/3

JSON Pointer also defines how to escape / in key fields (/ is ~1, ~ is ~0). That would add a second way to encode things in URLs though.

I think it's another option worth consideration.