mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API CHANGE: JSONDataFormatter builds JSON itself, changing it to use Convert::array2json() instead (fixes #5162, thanks sharvey)
This commit is contained in:
parent
7ebe602482
commit
a204c136fe
@ -26,27 +26,38 @@ class JSONDataFormatter extends DataFormatter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an XML representation of the given {@link DataObject}.
|
||||
*
|
||||
* @param DataObject $obj
|
||||
* @param $includeHeader Include <?xml ...?> header (Default: true)
|
||||
* @return String XML
|
||||
* Generate a JSON representation of the given {@link DataObject}.
|
||||
*
|
||||
* @param DataObject $obj The object
|
||||
* @param Array $fields If supplied, only fields in the list will be returned
|
||||
* @param $relations Not used
|
||||
* @return String JSON
|
||||
*/
|
||||
public function convertDataObject(DataObjectInterface $obj, $fields = null, $relations = null) {
|
||||
return Convert::array2json($this->convertDataObjectToJSONObject($obj, $fields, $relations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to do the conversion of a single data object. It builds an empty object and dynamically
|
||||
* adds the properties it needs to it. If it's done as a nested array, json_encode or equivalent won't use
|
||||
* JSON object notation { ... }.
|
||||
* @param DataObjectInterface $obj
|
||||
* @param $fields
|
||||
* @param $relations
|
||||
* @return EmptyJSONObject
|
||||
*/
|
||||
public function convertDataObjectToJSONObject(DataObjectInterface $obj, $fields = null, $relations = null) {
|
||||
$className = $obj->class;
|
||||
$id = $obj->ID;
|
||||
|
||||
$json = "{\n \"className\" : \"$className\",\n";
|
||||
|
||||
$serobj = ArrayData::array_to_object();
|
||||
|
||||
foreach($this->getFieldsForObj($obj) as $fieldName => $fieldType) {
|
||||
// Field filtering
|
||||
if($fields && !in_array($fieldName, $fields)) continue;
|
||||
|
||||
$fieldValue = $obj->$fieldName;
|
||||
if(is_object($fieldValue) && is_subclass_of($fieldValue, 'Object') && $fieldValue->hasMethod('toJSON')) {
|
||||
$jsonParts[] = "\"$fieldName\" : " . $fieldValue->toJSON();
|
||||
} else {
|
||||
$jsonParts[] = "\"$fieldName\" : " . Convert::raw2json($fieldValue);
|
||||
}
|
||||
$serobj->$fieldName = $fieldValue;
|
||||
}
|
||||
|
||||
if($this->relationDepth > 0) {
|
||||
@ -63,24 +74,24 @@ class JSONDataFormatter extends DataFormatter {
|
||||
} else {
|
||||
$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName");
|
||||
}
|
||||
$jsonParts[] = "\"$relName\" : { \"className\" : \"$relClass\", \"href\" : \"$href.json\", \"id\" : \"{$obj->$fieldName}\" }";
|
||||
$serobj->$relName = ArrayData::array_to_object(array("className" => $relClass, "href" => "$href.json", "id" => $obj->$fieldName));
|
||||
}
|
||||
|
||||
|
||||
foreach($obj->has_many() as $relName => $relClass) {
|
||||
if(!singleton($relClass)->stat('api_access')) continue;
|
||||
|
||||
|
||||
// Field filtering
|
||||
if($fields && !in_array($relName, $fields)) continue;
|
||||
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
|
||||
|
||||
$jsonInnerParts = array();
|
||||
$innerParts = array();
|
||||
$items = $obj->$relName();
|
||||
foreach($items as $item) {
|
||||
//$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID");
|
||||
$href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID");
|
||||
$jsonInnerParts[] = "{ \"className\" : \"$relClass\", \"href\" : \"$href.json\", \"id\" : \"{$obj->$fieldName}\" }";
|
||||
$innerParts[] = ArrayData::array_to_object(array("className" => $relClass, "href" => "$href.json", "id" => $obj->$fieldName));
|
||||
}
|
||||
$jsonParts[] = "\"$relName\" : [\n " . implode(",\n ", $jsonInnerParts) . " \n ]";
|
||||
$serobj->$relName = $innerParts;
|
||||
}
|
||||
|
||||
foreach($obj->many_many() as $relName => $relClass) {
|
||||
@ -90,42 +101,41 @@ class JSONDataFormatter extends DataFormatter {
|
||||
if($fields && !in_array($relName, $fields)) continue;
|
||||
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
|
||||
|
||||
$jsonInnerParts = array();
|
||||
$innerParts = array();
|
||||
$items = $obj->$relName();
|
||||
foreach($items as $item) {
|
||||
//$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID");
|
||||
$href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID");
|
||||
$jsonInnerParts[] = " { \"className\" : \"$relClass\", \"href\" : \"$href.json\", \"id\" : \"{$obj->$fieldName}\" }";
|
||||
$innerParts[] = ArrayData::array_to_object(array("className" => $relClass, "href" => "$href.json", "id" => $obj->$fieldName));
|
||||
}
|
||||
$jsonParts[] = "\"$relName\" : [\n " . implode(",\n ", $jsonInnerParts) . "\n ]";
|
||||
$serobj->$relName = $innerParts;
|
||||
}
|
||||
}
|
||||
|
||||
return "{\n " . implode(",\n ", $jsonParts) . "\n}"; }
|
||||
return $serobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an XML representation of the given {@link DataObjectSet}.
|
||||
* Generate a JSON representation of the given {@link DataObjectSet}.
|
||||
*
|
||||
* @param DataObjectSet $set
|
||||
* @return String XML
|
||||
*/
|
||||
public function convertDataObjectSet(DataObjectSet $set, $fields = null) {
|
||||
$jsonParts = array();
|
||||
foreach($set as $item) {
|
||||
if($item->canView()) $jsonParts[] = $this->convertDataObject($item, $fields);
|
||||
}
|
||||
$json = "{\n";
|
||||
$json .= '"totalSize": ';
|
||||
$json .= (is_numeric($this->totalSize)) ? $this->totalSize : 'null';
|
||||
$json .= ",\n";
|
||||
$json .= "\"items\": [\n" . implode(",\n", $jsonParts) . "\n]\n";
|
||||
$json .= "}\n";
|
||||
$items = array();
|
||||
foreach ($set as $do) $items[] = $this->convertDataObjectToJSONObject($do, $fields);
|
||||
|
||||
return $json;
|
||||
$serobj = ArrayData::array_to_object(array(
|
||||
"totalSize" => (is_numeric($this->totalSize)) ? $this->totalSize : null,
|
||||
"items" => $items
|
||||
));
|
||||
|
||||
return Convert::array2json($serobj);
|
||||
}
|
||||
|
||||
public function convertStringToArray($strData) {
|
||||
return Convert::json2array($strData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
@ -97,6 +97,18 @@ class ArrayData extends ViewableData {
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an associative array to a simple object
|
||||
*
|
||||
* @param array
|
||||
* @return obj $obj
|
||||
*/
|
||||
public static function array_to_object($arr = null) {
|
||||
$obj = new stdClass();
|
||||
if ($arr) foreach($arr as $name => $value) $obj->$name = $value;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is pretty crude, but it helps diagnose error situations
|
||||
|
@ -97,6 +97,15 @@ class ArrayDataTest extends SapphireTest {
|
||||
$this->assertEquals($arrayData->getArray(), $array);
|
||||
}
|
||||
|
||||
function testArrayToObject() {
|
||||
$arr = array("test1" => "result1","test2"=>"result2");
|
||||
$obj = ArrayData::array_to_object($arr);
|
||||
$objExpected = new stdClass();
|
||||
$objExpected->test1 = "result1";
|
||||
$objExpected->test2 = "result2";
|
||||
$this->assertEquals($obj,$objExpected, "Two objects match");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ArrayDataTest_ArrayData_Exposed extends ArrayData {
|
||||
|
@ -357,6 +357,22 @@ class RestfulServerTest extends SapphireTest {
|
||||
$this->assertEquals($responseArr['Rating'], 42);
|
||||
$this->assertNotEquals($responseArr['WriteProtectedField'], 'haxx0red');
|
||||
}
|
||||
|
||||
public function testJSONDataFormatter() {
|
||||
$formatter = new JSONDataFormatter();
|
||||
$single_do = $this->objFromFixture('Member', 'editor');
|
||||
|
||||
$this->assertEquals(
|
||||
$formatter->convertDataObject($single_do, array("FirstName", "Email")),
|
||||
'{"FirstName":"Editor","Email":"editor@test.com"}',
|
||||
"Correct JSON formatting with field subset");
|
||||
|
||||
$set = DataObject::get("Member");
|
||||
$this->assertEquals(
|
||||
$formatter->convertDataObjectSet($set, array("FirstName", "Email")),
|
||||
'{"totalSize":null,"items":[{"FirstName":"Editor","Email":"editor@test.com"},{"FirstName":"User","Email":"user@test.com"},{"FirstName":"ADMIN","Email":"ADMIN@example.org"}]}',
|
||||
"Correct JSON formatting on a dataobjectset with field filter");
|
||||
}
|
||||
|
||||
public function testApiAccessWithPOST() {
|
||||
$url = "/api/v1/RestfulServerTest_AuthorRating";
|
||||
|
Loading…
Reference in New Issue
Block a user