I want to get a V1 API call back in a format that I can use as JSON in Javascript in a component. How do I do that? For example:
(/categories/id/categoryName/labels)
<#assign someLabels = restadmin("/${context}/id/${contextId}/labels?restapi.response_format=json").labels.label?sort_by("text")/>
<script>
let someVar = [${someLabels}];
</script>
I know that V2 has the apiv2.toJson() method, but in this case V1 is the only way I know of to get a list of labels from a category, for example.
Solved! Go to Solution.
@Inactive User - You could use the restapi.response_format parameter to return JSON:
restapi.response_format=json
For more details see developer docs.
Alternatively, you can move your API requests to an endpoint and build a custom JSON response for that endpoint. Afterwards you can request your endpoint from your JS code.
@cike Thanks, however, I'm still unable to feed that directly into JS. To wit:
<#-- EX: https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels -->
<#assign someLabels = restadmind("/${context}/id/${contextId}/labels?restapi.response_format=json") />
<script>
console.log('script');
let labels = [${someLabels}];
console.log('labels',labels);
</script>
Gets me a freemarker error =>
How would creating an endpoint for this make that result any different?
@Inactive User - I think you have two errors in your REST call:
Firstly, you need to check your APIv1 request. I think you need to add an additional "/labels" path parameter to get a list of labels for your category:
<#-- APIv1 request: <a href="https://community-stage.jmp.com/restapi/vc/categories/id/[id]/labels/labels" target="_blank">https://community-stage.jmp.com/restapi/vc/categories/id/[id]/labels/labels</a> -->
<#assign someLabels = restadmind("/${context}/id/${contextId}/labels/labels?restapi.response_format=json") />
Take a look into the developers docs and APIv1 reference.
Secondly, to access the labels from the API response you need to access the labels object of the response. Your request will return something similar the example below:
{
"response": {
"status": "success",
"labels": {
"label": [
{
"type": "label",
"href": "/labels/id/1985",
"text": {
"type": "string",
"$": "Festnetz | Internet | Fernsehen"
},
"id": {
"type": "int",
"$": 1985
}
},
{
"type": "label",
"href": "/labels/id/1982",
"text": {
"type": "string",
"$": "Sonstiges"
},
"id": {
"type": "int",
"$": 1982
}
},
}
]
}
}
The have access to the label values, you have to access your Freemarker variable like this:
<#assign labels = someLabels.labels.label />
Be aware to add checks for empty responses or lists. Otherwise you will get Freemarker errors for accessing non-existing objects.
Will try that out, thanks. Then I can assign it to a JS variable like so?
var labels = [${labels}]
@Inactive User - You'll need to wrap your Freemarker variable in "", because Javascript can't handle ${labels} and will run into errors.
While the Freemarker JSON response should be valid you could parse the response with JSON.parse:
var labels = JSON.parse('${labels}')
Thanks, but I can't seem to get this to work no matter what I do:
Here's the JSON output from the call directly from the browser:
<a href="https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels/labels?restapi.response_format=json" target="_blank">https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels/labels?restapi.response_format=json</a>
OUTPUT:
{
"response": {
"status": "success",
"labels": {
"label": [
{
"type": "label",
"href": "\/labels\/id\/55",
"id": {
"type": "int",
"$": 55
},
"text": {
"type": "string",
"$": "Data Access and Manipulation"
}
},
{
"type": "label",
"href": "\/labels\/id\/28",
"id": {
"type": "int",
"$": 28
},
"text": {
"type": "string",
"$": "Data Exploration"
}
}
]
}
}
}
RELEVANT ENDPOINT CODE:
<#assign contextId = 'discovery'/>
<#assign context = 'categories'/>
<#-- MAIN LABELS -->
<#-- EX: <a href="https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels" target="_blank">https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels</a> -->
<#assign someLabels = restadmin("/${context}/id/${contextId}/labels/labels?restapi.response_format=json") />
var labels = JSON.parse('${someLabels}');
console.log('labels',labels);
Output, same Freemarker Error:
The error occurs, because you try to access the complete response object. But this is not supported.
The first element of the response you're able to access is the label array:
...
label: [
...
...
]
To solve the error, just add .labels.label to your code:
var labels = JSON.parse('${someLabels.labels.label}');
The keep your Javascript code as clean as possible, you could also add the .labels.label part to your Rest request:
<#assign someLabels = restadmin("/${context}/id/${contextId}/labels/labels?restapi.response_format=json").labels.label />
Sadly, this still throws the same error.
It would seem it should be easier than this to get something that's supposedly returned in JSON to initialize a JS variable with it...
<#assign contextId = 'discovery'/>
<#assign context = 'categories'/>
<#-- MAIN LABELS -->
<#-- EX: <a href="https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels" target="_blank">https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels</a> -->
<#assign someLabels = restadmin("/categories/id/discovery/labels/labels?restapi.response_format=json").labels.label />
var labels = JSON.parse('${someLabels.labels.label}');
console.log('labels',labels);
You must not add the .labels.label part in both locations. Just one is needed. I recommend the following:
<#assign contextId = 'discovery'/>
<#assign context = 'categories'/>
<#-- MAIN LABELS -->
<#-- EX: <a href="https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels" target="_blank">https://community-stage.jmp.com/restapi/v1/categories/id/discovery/labels</a> -->
<#assign someLabels = restadmin("/categories/id/discovery/labels/labels?restapi.response_format=json").labels.label />
var labels = JSON.parse('${someLabels}');
console.log('labels',labels);
Additionally, don't forget to wrap your Javascript in a <script> tag or Khoros' <liaAddScript> directive.
That didn't seem to make any difference either.
<#assign someLabels = restadmin("/categories/id/discovery/labels/labels?restapi.response_format=json").labels.label />
<script>
var labels = JSON.parse('${someLabels}');
console.log('labels',labels);
</script>
Same error.
No idea why this isn't working; I've opened a ticket with Khoros on it but thanks for the help. I'll update this thread when I get a reply from them.
@Inactive User - You could check if your request results in a non-empty list of labels:
<#if someLabels?? && someLabels?size gt 0>
<#-- Print ${someLabels?size} here -->
<#list someLabels as label>
<#-- Print ${label.text} here -->
</#list>
</#if>
Or you simple test your request through the browser or via other tools (curl, Postman).
Is it still the line
var labels = JSON.parse('${someLabels}');
which causes the error?
It's still the line JSON.parse() that's giving me the issue. And ${label.text} won't print because it's not actually a text node, it's an object, "$" has the text ... whew. Too confusing. Thanks tho.
The "$" sign shouldn't bother you. You can access the text or id value of labels as I mentioned. Freemarker handles this for you.
Did you try the snippet I provided to test your someLabels variable?
If this snippet works and will print some data, you can be sure your request/response is correct and there are maybe some limitations on accessing the object as you tried in your JS code.
I did use the snippet but it didn't print anything. When I removed the comment marks, did print in the enpdoint. Still can't get it into JS tho.
@Inactive User - Maybe we should go a step back and see if I understand your scenario in the right way 😊
You fetch labels of a node in an endpoint and want to access them via JS from a custom component, is that correct?
If so, I recommend the following:
If I'm wrong, it would be great if you could describe your intention, so I can figure out how to go on. 🙂
@cike Thanks, yes, that is correct.
However, the issue is that I can't get the endpoint to show up in JSON? If it's not JSON in the endpoint itself, how am I going to call that in a component and expect JSON? That make sense? Thanks 🙂
I guess the question is then, "how do I get an endpoint to return JSON"?
@Inactive User - Ok. Good to know that you want your endpoint to return JSON which than can be requested by your components.
You could use something like this to build your endpoint:
<#attempt>
<#assign someLabels = restadmin("/categories/id/discovery/labels? restapi.response_format=json").labels.label />
<#if someLabels?? && someLabels?size gt 0>
{
"response": {
"status": "successful",
"labels" : [
<#list someLabels as label>
"${label.text}"<#if (label?has_next)>,
</#list>
]
}
}
<#else>
{
"response": {
"status": "empty"
}
}
<#recover>
{
"response": {
"status": "error",
"message": "${.error?json_string}",
"query" : "${queryMsg?json_string}"
}
}
This should always return a JSON object from your endpoint. You should test your endpoint by directly accessing its Url, to see if things work as expected.
Thanks! I just added a few things to it to get it to work 100%:
<#attempt>
<#assign someLabels = restadmin("/categories/id/discovery/labels?restapi.response_format=json").labels.label />
<#if someLabels?? && someLabels?size gt 0>
{
"response": {
"status": "successful",
"labels" : [
<#list someLabels as label>
{"id":"${label.id}","text":"${label.text}"}<#if (label?has_next)>,
]
}
}
<#else>
{
"response": {
"status": "empty"
}
}
<#recover>
{
"response": {
"status": "error",
"message": "${.error?json_string}",
"query" : "${queryMsg?json_string}"
}
}
Great!
Hope everything works as you want, now. Requesting the endpoint via AJAX from a component shouldn't be that difficult from this point. 🙂
Thanks for all your help. Shouldn't have been that hard to begin with but ... some things are just a pain in Khoros Community... Thanks
Welcome to the Technology board!
Curious about our platform? Looking to connect on social technology? You've come to the right place!