Skip to content
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

Using an object in the properties of a feature in Styles Expressions #11685

Open
dragonfist453 opened this issue Apr 8, 2022 · 1 comment
Open

Comments

@dragonfist453
Copy link

Motivation

I was using a layer which has a property in the properties called "layer_properties" that contains an object containing further detailed properties unique to the layer type. For example, we have:

{
  "geometry": {
    "coordinates": [
      -169.4,
      -47.5
    ],
  "type": "Point"
  },
  "id": "JET_STREAM_POINT_DATA_fid--476b30b2_17f98bc5c3d_-5d37",
  "properties": {
    "validTime": 1649397600000,
    "valid_time_str": "08Apr22 06:00Z",
    "layer_properties": {
      "jet_wind_level": "290",
      "jet_wind_speed": "90"
    },
    "forecast_period": "018HR",
    "layer_name": "JET_STREAM_POINT_DATA"
  },
  "type": "Feature"
}

Using the existing API, there is no easy way to access jet_wind_level or jet_wind_speed inside layer_properties as get will give me layer_properties as a string like "{jet_wind_level: 290, jet_wind_speed: 90}". This does not help me much and I need to implement an algorithm in styles API that slices the string to get me the value given attribute.

A lot of layers for weather have these sort of composite objects not necessarily named "layer_properties" that may need to be accessed.

Design

  • A new operator like 'get-composite' that does this
  • An extension to 'get' to accomodate a JSON string and take attributes from them
  • Making get return an object if it's noticed to contain it or provide a flag for it

It helps a lot for data that could be provided this way and it will make it a lot more powerful. There should be no drawbacks as it just makes the styles expressions API work for more versatile use-cases.

Mock-Up

It could be tried as a ['get-composite', 'jet_wind_level', 'layer_properties'] (as per above given example) to provide the string "290" by accessing the object conveniently. This should ease up and make this wonderful API much more convenient to use.

Alternative followed for this problem

For others facing this problem, I had to implement a simple slicing function that looks complex like so:

const sliceAttrValueFromCompositeObject = (attribute: string, compositeObjectKey: string, endchar: string, separator: string = ':'): Array<any> => {
  return [
    'slice', // Slice the sliced string with the given indices to get only the value part for a given attribute
    ['slice',['get', compositeObjectKey],['index-of', attribute+separator, ['get', compositeObjectKey]]], // Slice string such that we only have the JSON from the attribute till the end so that we only operate on that
    ['+', ['index-of', attribute+separator, ['slice',['get', compositeObjectKey],['index-of', attribute+separator, ['get', compositeObjectKey]]]], ['length', attribute+separator]], // Get the index of the attribute name in the sliced string and then add the length of the attribute+separator to go to the value part
    ['index-of', endchar, ['slice',['get', compositeObjectKey],['index-of', attribute+separator, ['get', compositeObjectKey]]]] // Get the index of the nearest end char to slice till
  ]
}

const getAttrFromCompositeObject = (attribute: string, compositeObjectKey: string = 'layer_properties', separator: string = ':'): Array<any> => {
  return [
    'case', // If there is a comma present in the sliced string, slice till ',' else slice till '}' (which notifies that this is last or only attribute in JSON)
    ['!=', ['index-of', ',', ['slice',['get', compositeObjectKey],['index-of', attribute+separator, ['get', compositeObjectKey]]]], -1],
    sliceAttrValueFromCompositeObject(attribute, compositeObjectKey, ',', separator),
    sliceAttrValueFromCompositeObject(attribute, compositeObjectKey, '}', separator)
  ]
}

Using this as getAttrFromCompositeObject('jet_wind_speed') would get me the data from layer_properties but this only works for text-field or icon-image or for any place that takes a value type. When a string is asked, like in a "formatted" type, it will not work and that does lead to problems. If this could be completely solved by adding a feature to access composite objects, it would make the API very powerful for anybody using it

@mourner
Copy link
Member

mourner commented May 2, 2022

See also #2434 for a similar request, with a lengthy discussion. The problem is that GeoJSON is converted into vector tiles for processing & rendering, and the vector tile specification does not support nested properties — fixing this is a pretty difficult architectural problem, more than it appears at first.

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

No branches or pull requests

2 participants