Creating dynamic records. Additional documentation required #1819
-
QuestionHow can I create 2.0 record with dynamic properties and convert it to json? ContextGeneralI want to print information about multiple sources in json format in telnet command response. I expect result to be {
"$id": "sourceInfoSchema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"success": {
"type": "boolean"
}
},
"additionalProperties": {
"$ref": "#/definitions/sourceInfo"
},
"definitions": {
"sourceInfo": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"isFallible": {
"type": "boolean"
},
"isReady": {
"type": "boolean"
},
"remainingTime": {
"oneOf": [
{
"type": "number"
},
{
"type": "null"
}
]
},
"clockTime": {
"type": "number"
}
}
}
}
} For example this is valid response {
"success": true,
"fallback_9550": {
"name": "Full",
"isFallible": false,
"isReady": true,
"remainingTime": null,
"clockTime": 570.96
}
}
1.4.4In 1.4 there were no records. Also, there's no way to generate objects with different types(not sure). So I can return {
"fallback_9550": {
"name": "Full",
"isFallible": "false",
"isReady": "true",
"remainingTime": "inf",
"clockTime": "570.96"
}
} I can't set property {
"$id": "sourceInfoSchema_1.4.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/sourceInfo"
},
"definitions": {
"sourceInfo": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"isFallible": {
"enum": ["true", "false"]
},
"isReady": {
"enum": ["true", "false"]
},
"remainingTime": {
"$ref": "#/definitions/liquidSoapFloat"
},
"clockTime": {
"$ref": "#/definitions/liquidSoapFloat"
}
}
},
"liquidSoapFloat": {
"oneOf": [
{
"type": "string",
"pattern": "^\\d+\\.\\d+$"
},
{
"const": "inf"
}
]
}
}
} I have created a functions to create this json
And call the function like this
2.0.0-beta.3In 2.0.0 it's possible to create records, that look like json. But there's no documentation how can iterate over record
Iterate over record (expected)
But this will not work because I can't reduce over records. ERROR: (Failure "TODO: JSON of method not yet implemented")
I want to capture an error. Function renamed by new variable
In 2.0.0 this will not work, because Record properties in loop
Anything set inside the loop will remain inside the loop Dereference new record property from variable
Didn't find how to do this in documentation and tests Can't change set record properties in
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Hi! For advanced use of JSON like this I would recommend Iterate over record (expected) The function However, you can also create JSON objects using associative lists, in which case, keys can be dynamic:
Here's a fixed version of your function:
Then you can use a I have used a couple of tricks, in particular the use of ERROR: (Failure "TODO: JSON of method not yet implemented") You are right that the failure should be catchable. This is fixed in 09beaad. However, the code needs to be adapted to the functional style of liquidsoap scripts. This should work:
Function renamed by new variable This operator exists in Record properties in loop Yes, this is the same issue with static typing. Again, I would recommend using an associative list and Dereference new record property from variable I don't know if this is possible at the moment. You probably would need to redefine a new record with all the keys that you want to list explicitly listed. Otherwise, we wouldn't be able to type the function. Here, too, switching to associative lists will solve your issue. Can't change set record properties in list.fold Same suggestion re: associative list. Ultimately, I would say that the only missing spot at the moment is the ability to generate a json object using multiple sources, for instance an associative list (object with dynamic keys but same type for all values) and another module (static keys but multiple possible types for the values). I've captured that in this ticket: #1821 |
Beta Was this translation helpful? Give feedback.
-
Just created a PR to add support for generic abstract json objects: #1824 |
Beta Was this translation helpful? Give feedback.
-
My script
And the result {
"source.fail_0": {
"remainingTime": 0,
"clockTime": 35.56,
"isReady": false,
"isFallible": true,
"namespace": "Jingles"
},
"source.fail_3": {
"remainingTime": 0,
"clockTime": 35.56,
"isReady": false,
"isFallible": true,
"namespace": "Music_3"
},
"source.fail_2": {
"remainingTime": 0,
"clockTime": 35.56,
"isReady": false,
"isFallible": true,
"namespace": "Music_2"
},
"source.fail_1": {
"remainingTime": 0,
"clockTime": 35.56,
"isReady": false,
"isFallible": true,
"namespace": "Music_1"
},
"single_0": {
"remainingTime": 254.730997732,
"clockTime": 35.56,
"isReady": true,
"isFallible": false,
"namespace": "Security"
},
"switch_3": {
"remainingTime": 0,
"clockTime": 35.56,
"isReady": false,
"isFallible": true,
"namespace": "Schedule"
},
"switch_6": {
"remainingTime": null,
"clockTime": 35.56,
"isReady": true,
"isFallible": false,
"namespace": "Full"
},
"add_0": {
"remainingTime": null,
"clockTime": 35.56,
"isReady": true,
"isFallible": false,
"namespace": "Radio"
}
} But if I try to uncomment
then I'll get
Maybe I'm not so good at creating json interfaces, and result should look like {
"success": true,
"sources": {
"add_0": {
"clockTime": 35.56,
"isReady": true,
"issFallible": false,
"namespace": "Radio"
}
}
} because I can then iterate over if(obj.success === true) {
Object.Entries(obj.sources).forEach(doSomething)
} But It's possible to do that even if use object as is if(obj.success === true) {
Object.Entries(obj).filter((key) => key !== 'success').forEach(dosomething)
} |
Beta Was this translation helpful? Give feedback.
Hi!
For advanced use of JSON like this I would recommend
2.0.0
indeed. I think your assessment about not being able to create JSON objects of multiple types in1.4.4
is indeed correct.Iterate over record (expected)
The function
formatSourceInfoString
cannot work as-is because records are statically typed so, we need to know all the types in advance, including all key names. Thus, thesourceId
key cannot be dynamic.However, you can also create JSON objects using associative lists, in which case, keys can be dynamic:
Here's a fixed version of your function: