Saving an object as JSON, and then loading it later? - php

I know how to JSON encode and decode an object. That's no biggie. However, I've reached a situation where I need to save $this as a JSON string, and then later, populate $this's attributes from that JSON string.
In other words, I don't want to get a new instance of an object with the data from the JSON string, I want to apply it to an existing object.
How can I do that?

You can get the defined attributes of an object using get_object_vars() http://php.net/manual/en/function.get-object-vars.php
class MyClass
{
function populateFromJSON($data)
{
$o = json_decode($data);
$attributes = get_object_vars($o);
if (is_array($attributes)) {
foreach ($attributes as $name => $val) {
$this->$name = $val;
}
}
}
}

Related

How can I convert an object to a specific JSON format?

json_encode converts an object to:
{
"height":10,
"width":20,
"depth":5
}
But I need it to include the objects class name as well:
{
"cuboid":
{
"height":10,
"width":20,
"depth":5
}
}
public function toJson() {
return json_encode([get_class($this) => $this]);
}
Hope this will help you out. Here we are converting json to array and putting it into an array of field cuboid
Try this code snippet here
<?php
ini_set('display_errors', 1);
$json='{
"height":10,
"width":20,
"depth":5
}';
$result["cuboid"]=json_decode($json,true);
echo json_encode($result,JSON_PRETTY_PRINT);
You can use get_class to get class name of an object.
$json = json_encode(array(get_class($object) => $object));
Rules for json_encode
if you have an object it will be encode to {'pro1':'value'}
if you have an array it will be encode to ['value']
if you have an string it will be encode to 'value'
Note: If you have an assoc-array in php, it becomes an object in json! If you have an index-array it will be an array in json. Dont mix index & assoc!
Test this bad pratice: echo json_encode(array('foo' => 'bar',1,2)); Result is this bad syntax {"kitten":"test","0":1,"1":2} (propertie-names should NOT be numbers !!!)
So if you want and object under a property name do this
$obj = new stdClass();
$obj->prop = array(1,2,'a');
$newObject = new stdClass();
$newObject->objname = $obj;
print_r(json_encode($newObject));
Becomes: {'objname':{'prop':[1,2,'a']}}
Have a nice day :-)

When using simplexml_load_string all the nodes are of type string... a way to convert to int, float, etc

I get an XML response from an API and I use simplexml_load_string to convert it to an object in PHP. I then store the object into a mongo database directly and it works perfect. The issue is since it comes from XML all the nodes are of type "string" in mongo. Is there a fancy or simple way to loop through all the nodes in the PHP object and convert to integer or float or boolean? If I pull out all the nodes manually I can use "intval" and "floatval" but I am looking to see if it may be possible to do this automatically based on the content. ie. Loop through all the nodes regardless of depth and do a preg_match for 0-9 to set the item to type "int". If 0-9 w/ . set to float. If true/false/0/1 set to bool. Leave the rest strings. Any ideas?
$this->response_object = simplexml_load_string($xml);
Values in SimpleXML are always of type string within PHP. And due to the magic nature of the SimpleXMLElement class, you can not change that by extending from it.
However, you can extend from SimpleXMLElement and add a function called typecastValue() (exemplary) which does the work. You then can specify with simplexml_load_string that you want to use that class instead of the default SimpleXMLElement class.
class MyElement extends SimpleXMLElement
{
public function typecastValue() {
$value = trim($this);
// check if integer, set as float
if (preg_match('/^[0-9]{1,}$/', $value)){
return floatval($value);
}
// check if float/double
if (preg_match('/^[0-9\.]{1,}$/', $value)){
return floatval($value);
}
// check if boolean
if (preg_match('/(false|true)/i', $value)){
return (boolean)$value;
}
// all else leave as string
return $value;
}
}
As you can see, the code is very similar to your typecast function above, it just uses $this to obtain the original value.
Functions like xml_object_to_array are still generally superfluous, as the parsing is already done and you're more concerned about accessing and serializing the date in the XML into an array (I suspect this is due to JSON requirements of Mongodb but I don't know). If so, PHP JSON Serialization would/could be more appropriate, for SimpleXMLElement we have existing material on the site already.
Json Encode or Serialize an XML
I think I found my own answer (unless you have a more elegant way)...
function xml_object_to_array($xml) {
if ($xml instanceof SimpleXMLElement) {
$children = $xml->children();
$return = null;
}
foreach ($children as $element => $value) {
if ($value instanceof SimpleXMLElement) {
$values = (array)$value->children();
if (count($values) > 0) {
$return[$element] = xml_object_to_array($value);
} else {
if (!isset($return[$element])) {
$return[$element] = typecast_value($value);
} else {
if (!is_array($return[$element])) {
$return[$element] = array($return[$element], typecast_value($value));
} else {
$return[$element][] = typecast_value($value);
}
}
}
}
}
if (is_array($return)) {
return $return;
} else {
return false;
}
}
// auto typecast value for mongo storage
function typecast_value($value){
$value = trim($value);
// check if integer, set as float
if(preg_match('/^[0-9]{1,}$/', $value)){
return floatval($value);
}
// check if float/double
if(preg_match('/^[0-9\.]{1,}$/', $value)){
return floatval($value);
}
// check if boolean
if(preg_match('/(false|true)/i', $value)){
return (boolean)$value;
}
// all else leave as string
return $value;
}

Foreach array within an object

I've got a PHP object. One of the values within the object is in array. I'm trying to get a foreach to just read the array within the object but it doesn't seem to be working.
PHP:
foreach ($object->ArrayName as $value) {
echo $value;
}
is there any way of doing this?
well, if you have an object but you don't know which property is an array, you need to catch them all and verify if they are an array:
// get each value of the object and call it as property
foreach(get_object_vars($object) as $property) {
// if this property is an array...
if (is_array($property) {
// ... access to every value of that array
foreach($property as $value) {
// $property is your array and $value is every value
// here you can execute what you need
}
}
}
Use
is_array($obj)
to validate whether it's an array or not.
you said your php object contains arrays, hence you need to use 2 foreach loops like this.
<?php
foreach($object->ArrayName as $value) {
foreach($value as $item) {
echo $item;
}
}
?>
if the loop is withing the object wich mean inside the class use $this instead :
foreach ($this->ArrayName as $value) {
echo $value;
}

PHP reference variable by case-insensitive string

PHP 5. I'm in a situation where I need to translate a case-insensitive url query to member variables in a PHP object. Basically, I need to know what member variable the url query key points to so I can know if it's numeric or not.
For example:
class Foo{
$Str;
$Num;
}
myurl.com/stuff?$var=value&num=1
When processing this URL query, I need to know that "str" associates with Foo->$Str, etc. Any ideas on how to approach this? I can't come up with anything.
Try something like this.
function fooHasProperty($foo, $name) {
$name = strtolower($name);
foreach ($foo as $prop => $val) {
if (strtolower($prop) == $name) {
return $prop;
}
}
return FALSE;
}
$foo = new Foo;
// Loop through all of the variables passed via the URL
foreach ($_GET as $index => $value) {
// Check if the object has a property matching the name of the variable passed in the URL
$prop = fooHasProperty($foo, $index);
// Object property exists already
if ($prop !== FALSE) {
$foo->{$prop} = $value;
}
}
And it may help to take a look at php's documentation on Classes and Objects.
Example:
URL: myurl.com/stuff?var=value&num=1
Then $_GET looks like this:
array('var' => 'value', 'num' => '1')
Looping through that, we would be checking if $foo has a property var, ($foo->var) and if it has a property num ($foo->num).

How to parse stdClass object?

I have a SOAP response whose var_dump looks like this:
object(stdClass)[14]
public 'GetClientsResult' =>
object(stdClass)[15]
I can't figure out how to parse this for the life of me, I've never used stdClass before.
How can I parse this response in PHP?
For starters, you can cast it into an array (assuming the object is stored in $response):
$response = (array) $response;
Or you can access things by:
$response->GetClientResult->otherStuff;
An StdClass is an empty class where you can set and get property values. An example:
<?php
// $response is a normal array
$response['GetClientResult'] = 'foo'; // set
$response['GetClientResult']; // get
// $response is a StdClass
$response->GetClientResult = 'foo'; // set
$response->GetClientResult; // get
?>
And if you want to cast the class back to an array you can use:
$response = (array) $response
And if you want to do that recursive, because you have multiple StdClasses:
function StdClass2array(StdClass $class)
{
$array = array();
foreach ($class as $key => $item)
{
if ($item instanceof StdClass) {
$array[$key] = StdClass2array($item);
} else {
$array[$key] = $item;
}
}
return $array;
}

Categories