Opened 20 months ago
Last modified 3 months ago
#3869 assigned Feature Request
JSON viewtype rework
| Reported by: | ewinslow | Owned by: | cash |
|---|---|---|---|
| Priority: | normal | Milestone: | Elgg 1.9.0 |
| Component: | Core | Version: | 1.8 |
| Severity: | minor | Keywords: | |
| Cc: | brett@… | Difficulty: |
Description (last modified by ewinslow)
Currently the json viewtype returns rather unhelpful results. If I visit /view/1?view=json, I'm expecting something like this:
{
"name": "My Site Name",
"guid": 1,
"type": "site"
}
Instead we something like:
{
'site': {
'default': [
{... entity info ... }
]
}
}
This is because the views are shoving everything into a global and then the page shell outputs the global at the end. It does this because (I assume), there are issues if you just json_encode the results directly into the page. However, when it requests an entity, an entity is not returned, but instead a structure that happens to have 1 entity in it. If a list is requested, a list is not returned, but only that same structure that happens to have limit items in it, and even in that case not guaranteed to preserve the order (e.g. if multiple types/subtypes are requested).
I propose we allow developers to explicitly return any value from a view, rather than always relying on the output buffer results (though obviously still accepting OB-based results, since that is most convenient for markup languages). That way, the json views could return an object version of whatever they're exporting, list views could collate them into an array, and then the page shell view can have the resonsibility of actually encoding the results as JSON.
This would require some changes to elgg_view, of course, to support these return values. Thoughts?
Change History (9)
comment:1 Changed 20 months ago by cash
comment:2 Changed 20 months ago by ewinslow
I was just thinking something along these lines:
$list = array();
foreach ($entities as $entity) {
$list[] = elgg_view_entity($entity);
}
return $list;
comment:3 Changed 13 months ago by ewinslow
- Description modified (diff)
- Milestone changed from Needs Review to Long Term Discussion
comment:4 Changed 13 months ago by ewinslow
Maybe we don't need to complicate this so much by adding these new semantics to views.
In json there are just objects and arrays.
We can just do echo json_encode($entity->toJson()); in the entity views, then the list views would just do:
$items = array();
foreach ($entities as $entity) {
$items[] = elgg_view_entity($entity);
}
echo '[' . implode($items, ',') . ']';
comment:5 Changed 12 months ago by markharding
There is also the problem when using web services were the json output will just produce blank arrays if you don't manually stipulate each attributes.
eg.
$user = get_user_by_username($username); $wire_posts = elgg_get_entities(array( 'type' => 'object', 'subtype' => 'thewire', 'owner_guid' => $user->guid, )); return $wire_posts;
actually returns:
{"status":0,"result":[{},{},{},{}]}
I'm not sure it is a good thing to have to keep having to replicate near enough the same code over and over again.
comment:6 Changed 12 months ago by markharding
I have written a function which outputs json quite nicely.
function restful_encode(array $options = array()){
extract($options);
foreach($entities as $single){
foreach($keys as $key){
$a[$key] = $single->$key;
}
if(!isset($owner_block) || $owner_block == true){
$owner = get_entity($single->owner_guid);
$a['owner']['guid'] = $owner->guid;
$a['owner']['name'] = $owner->name;
$a['owner']['avatar_url'] = get_entity_icon_url($owner,'small');
}
$output[] = $a;
}
return $output;
}}}}
You still have to go through the json output view but it provides a nicer and standard way of outputting the data.
comment:7 Changed 3 months ago by cash
- Milestone changed from Long Term Discussion to Elgg 1.9.0
comment:8 Changed 3 months ago by cash
I'm taking an approach similar to http://trac.elgg.org/ticket/3869#comment:4
comment:9 Changed 3 months ago by cash
- Owner set to cash
- Status changed from new to assigned

JSON is a pain to work with due to how Elgg handles views. Something needs to change. This looks like a ticket that could use some experimentation before we discuss how to implement.
Would we be happy with restricting the returns to either individual entities or lists of entities?
The issue that I'm thinking about is how to handle multiple views returning objects - how do you assemble them into a structure...