取得從 JSON Web 服務檢索的資料並將其轉換為巢狀物件和陣列 - 使用您自己的模型類別。
從基本物件開始,它將 JSON 資料映射到類別屬性上,將它們轉換為正確的簡單類型或物件。
它有點像 PHP 的SoapClient
為您提供的本機 SOAP 參數映射,但針對的是 JSON。它不依賴任何模式,只依賴 PHP 類別定義。
類型檢測透過解析類別屬性的類型宣告和@var
docblock 註解以及 setter 方法中的類型提示來運作。
您不必透過新增 JSON 特定程式碼來修改模型類別;它透過解析已經存在的文件區塊來自動工作。
該庫沒有依賴項。
關鍵字:反序列化、水化
內容
map()
模型類別需要手寫
由於JsonMapper不依賴任何模式資訊(例如來自json-schema),因此無法自動產生模型類別。
netresearch/jsonmapper
JsonMapper
物件實例map
或mapArray
方法映射一個普通物件:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactObject = $ mapper -> map ( $ jsonContact , new Contact ());
// or as classname
$ contactObject = $ mapper -> map ( $ jsonContact , Contact::class);
映射物件數組:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactsArray = $ mapper -> mapArray (
$ jsonContacts , array (), ' Contact '
);
除了array()
之外,您還可以使用ArrayObject
和衍生類別,以及實作ArrayAccess
類別。
來自地址簿 Web 服務的 JSON:
{
"name" : "Sheldon Cooper" ,
"address" : {
"street" : "2311 N. Los Robles Avenue" ,
"city" : "Pasadena"
}
}
您當地的Contact
方式:
<?php
class Contact
{
/**
* Full name
*/
public string $ name ;
public ? Address $ address ;
}
您的本地Address
類別:
<?php
class Address
{
public $ street ;
public $ city ;
public function getGeoCoords ()
{
//do something with $street and $city
}
}
您的申請代碼:
<?php
$ json = json_decode ( file_get_contents ( ' http://example.org/sheldon.json ' ));
$ mapper = new JsonMapper ();
$ contact = $ mapper -> map ( $ json , new Contact ());
echo " Geo coordinates for " . $ contact -> name . " : "
. var_export ( $ contact -> address -> getGeoCoords (), true );
JsonMapper
使用多個來源以以下順序偵測屬性的正確類型:
Setter 方法 ( set
+ ucwords($propertyname)
)
底線“ _
”和連字符“ -
”使下一個字母大寫。屬性foo_bar-baz
導致 setter 方法setFooBarBaz
。
如果方法簽名中有類型提示,則使用其類型:
公用函數 setPerson(聯絡人 $person) {...}
檢查該方法的文件區塊是否有@param $type
註解:
/** * @param Contact $person 此應用程式的主要聯絡人 */ 公用函數 setPerson($person) {...}
如果無法偵測到類型,則將純 JSON 值傳遞給 setter 方法。
類別屬性類型(自 PHP 7.4 起):
公共聯絡人$人;
建構函數屬性提升類型(自 PHP 8.0 起):
公共函數 __construct(受保護的聯絡人 $person) {}
類別屬性的@var $type
docblock註解:
/** * @var myapplicationmodelContact */ 公共$人;
該財產必須是公共的才能直接使用。您也可以使用 $bIgnoreVisibility 來利用受保護的私有屬性。
如果無法偵測到類型,則該屬性將取得純 JSON 值集。
如果找不到屬性,JsonMapper 會嘗試以不區分大小寫的方式尋找該屬性。然後,JSON 屬性isempty
將映射到 PHP 屬性isEmpty
。
筆記
您必須提供完全限定的命名空間才能使類型正常運作。相對類別名稱在目前類別命名空間的上下文中進行評估,而不考慮可能存在的任何導入。
PHP 不會透過反射提供導入;註釋文字僅包含類型的文字文字。出於效能原因,JsonMapper 不會自行解析原始程式碼來偵測和擴充任何導入。
簡單類型
string
bool
, boolean
int
, integer
double
float
array
object
mixed
類別名,有命名空間和不含命名空間
Contact
- 如果 JSON 值為null
則會拋出例外簡單型別和類別名的陣列:
int[]
Contact[]
多維數組:
int[][]
TreeDeePixel[][][]
簡單型別和類別名稱的 ArrayObjects:
ContactList[Contact]
NumberList[int]
支援枚舉,帶或不帶命名空間
Suit:string|Suit:int
- 如果枚舉中不存在 JSON 值,則會拋出異常
可空類型:
int|null
或?int
- 如果 JSON 中的值為null
,則將為null
,否則它將是一個整數Contact|null
或?Contact
- 如果 JSON 中的值為null
,則將為null
,否則它將是Contact
類型的對象ArrayObject 和擴充類別被視為陣列。
無類型或mixed
類型的變數將直接取得 JSON 值集,無需任何轉換。
有關詳細信息,請參閱 phpdoc 的類型文件。
筆記
從版本 5 開始,出於安全原因,此功能預設為停用狀態。
當要建立物件但 JSON 僅包含簡單類型(例如字串、浮點數、布林值)時,該值將傳遞給類別的建構子。例子:
PHP程式碼:
public DateTime $ date ;
JSON:
{ "date" : "2014-05-15" }
這將導致調用new DateTime('2014-05-15')
。
當變數被定義為抽象類別或介面的物件時,JsonMapper 通常會嘗試直接實例化它們並崩潰。
使用 JsonMapper 的$classMap
屬性,您可以指定要實例化哪些類別:
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = ' Bar ' ;
$ jm -> map (...);
當變數定義為Foo
類型時,這將建立Bar
類型的物件。
如果需要動態確定實際的實作類別(例如在聯合的情況下),也可以使用可呼叫物件。映射的類別(下面範例中的“Foo”)和 Json 資料作為參數傳遞到呼叫中。
$ mapper = function ( $ class , $ jvalue ) {
// examine $class and $jvalue to figure out what class to use...
return ' DateTime ' ;
};
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = $ mapper ;
$ jm -> map (...);
當 JSON 屬性為null
時,JsonMapper 會引發異常,除非 PHP 類別屬性具有可為 null 的類型 - 例如Contact|null
或?Contact
。
如果您的 API 包含許多可能為null
字段,並且您不希望所有類型定義都可為空,請設定:
$ jm -> bStrictNullTypes = false ;
從版本 5.0.0 開始,陣列中的null
值會導致JsonMapper_Exception
,除非型別可為 null - 例如array[?string]
或array[string|null]
。
要恢復先前的行為(即使沒有聲明也允許空值)設定:
$ jm -> bStrictNullTypesInArrays = false ;
JsonMapper 的setLogger()
方法支援所有 PSR-3 相容的記錄器實例。
記錄的事件:
在開發過程中,API 經常會改變。為了獲得有關此類變更的通知,可以將 JsonMapper 配置為在資料遺失或未知的情況下拋出異常。
當 JsonMapper 看到 JSON 資料中未在 PHP 類別中定義的屬性時,可以透過設定$bExceptionOnUndefinedProperty
讓它拋出異常:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnUndefinedProperty = true ;
$ jm -> map (...);
您也可以選擇將可呼叫設為$undefinedPropertyHandler
來自行處理這些屬性:
/**
* Handle undefined properties during JsonMapper::map()
*
* @param object $object Object that is being filled
* @param string $propName Name of the unknown JSON property
* @param mixed $jsonValue JSON value of the property
*
* @return void
*/
function setUndefinedProperty ( $ object , $ propName , $ jsonValue )
{
$ object ->{ ' UNDEF ' . $ propName } = $ jsonValue ;
}
$ jm = new JsonMapper ();
$ jm -> undefinedPropertyHandler = ' setUndefinedProperty ' ;
$ jm -> map (...);
或者,如果您讓 JsonMapper 為您處理 setter,您可以從$undefinedPropertyHandler
傳回字串,該字串將用作屬性名稱。
/**
* Handle undefined properties during JsonMapper::map()
*
* @param object $object Object that is being filled
* @param string $propName Name of the unknown JSON property
* @param mixed $jsonValue JSON value of the property
*
* @return void
*/
function fixPropName ( $ object , $ propName , $ jsonValue )
{
return ucfirst ( $ propName );
}
$ jm = new JsonMapper ();
$ jm -> undefinedPropertyHandler = ' fixPropName ' ;
$ jm -> map (...);
筆記
僅當 $bStrictObjectTypeChecking 保持啟用狀態時才有效。
PHP 類別中的屬性可以透過將@required
放入其文件區塊中來標記為「必需」:
/**
* @var string
* @required
*/
public $ someDatum ;
當 JSON 資料不包含此屬性時,JsonMapper 將在啟動$bExceptionOnMissingData
時拋出JsonMapper_Exception
:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnMissingData = true ;
$ jm -> map (...);
選項$bRemoveUndefinedAttributes
會導致 JsonMapper 從最終物件中刪除屬性(如果它們不在 JSON 資料中):
$ jm = new JsonMapper ();
$ jm -> bRemoveUndefinedAttributes = true ;
$ jm -> map (...);
您可以透過將$bIgnoreVisibility
設為 true 來允許對應到私有和受保護的屬性和 setter 方法:
$ jm = new JsonMapper ();
$ jm -> bIgnoreVisibility = true ;
$ jm -> map (...);
當變數的類型是類別且 JSON 資料是簡單類型(如string
時,JsonMapper 可以在配置時將此值傳遞給類別的建構子:
$ jm = new JsonMapper ();
$ jm -> bStrictObjectTypeChecking = false ;
$ jm -> map (...);
這可用於從日期字串自動初始化 DateTime 物件。
不過,停用這種嚴格的物件類型檢查可能會導致問題:
@required
屬性不會被填充筆記
在版本 5 中預設值從false
更改為true
以提高安全性。
現在,如果您想將簡單類型傳遞給類別建構函數,您必須選擇加入。
map()
您可能希望將數組資料傳遞到透過呼叫獲得的map()
中
json_decode ( $ jsonString , true )
預設情況下,JsonMapper 會拋出異常,因為map()
需要一個物件作為第一個參數。您可以透過將$bEnforceMapType
設定為false
來避免這種情況:
$ jm = new JsonMapper ();
$ jm -> bEnforceMapType = false ;
$ jm -> map (...);
JsonMapper 能夠在映射完成後直接在每個物件上呼叫自訂方法:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> map (...);
現在,每個映射物件上都會呼叫afterMapping()
(如果該類別具有該方法)。
您可以將其他參數傳遞給映射後回呼:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> postMappingMethodArguments = [ 23 , ' foo ' ];
$ jm -> map (...);
透過 Packagist 的 Composer:
$ 作曲家需要 netresearch/jsonmapper
替代方案
JsonMapper 根據 OSL 3.0 獲得許可。
JsonMapper 遵循 PEAR 編碼標準。
克里斯蒂安‧韋斯克 (Christian Weiske),cweiske.de