Skip to content
ryobg edited this page Feb 15, 2018 · 2 revisions

Overview

This feature simplifies an access to values of nested objects via group of solve* and solve*Setter functions. Each function has an argument (path specifier), telling the function how to walk to, or search for, a given value. Path is a set of joined elements: element1, element2, ... elementN and each element is one of:

  • [Index]
  • [formId]
  • [__formData|Plugin|formId] in case element accesses JArray, JFormMap or JIntMap
  • .stringKey in case element accesses JMap.

For example, the solveInt function in the code below:

solveInt(objectA, ".keyA[4].keyB")
-- and objectA may look like this:
objectA = {
  "keyA": [0,0,0,0,{"keyB": "anything"}]
}

retrieves a value which is associated with keyB of JMap, which is located at the 4-th position of a JArray container, which in turn is associated with keyA of objectA (a JMap). Huh.

The solve*Setter set of functions change (assign) a value. They have also an optional createMissingKeys argument which if enabled, will insert any missing JMap key during path traversal. For example, calling:

solveFltSetter(objectA, ".key1.key2", 3.14, true)

on an empty objectA will create new JMap containing the {"key2", 3.14} pair. Note that this also associates the objectA with the new JMap - in JSON terms, the structure {"key1", {"key2": 3.14}} will be created.

The solve*Setter functions fail if createMissingKeys is disabled and any key in the path is missing.

Another example, showing how these can be used for simple gets and sets:

info = {
    "classicPreset" :  {
        "campfileLighting" : "Automatic"
    },
    "numbers" : [0, 1, 2, 3]
}

string lightingType = JValue.solveStr(info, ".classicPreset.campfileLighting")
JValue.solveStrSetter(info, ".classicPreset.campfileLighting", "Non-Automatic")
int firstNumber = JValue.solveInt(info, ".numbers[0]")
JValue.solveIntSetter(info, ".numbers[0]", 10)

Key naming convention

In order to make path resolving and collection operators function properly, string keys should consist of ASCII characters and should not contain decimal characters, square brackets, or the @ character. Also the dot symbol . has a special meaning, for instance, the following code will fail to work:

obj = { "invalid.key" : {"k": 10} }

solveInt(map, ".invalid.key.k") is 0

-- although it's still possible to access that value in the traditional way:
getObj(map, "invalid.key") is {"k": 10}

This convention applies to every key string, not just to the JMap keys. It affects JFormDB storage name and keys as well as the JDB.setObj key. Key naming shouldn't matter if you don't use path resolving.