Home » Php » php – JSON object instead of array when a single element is present on XML SOAP response

php – JSON object instead of array when a single element is present on XML SOAP response

Posted by: admin February 25, 2020 Leave a comment

Questions:

I am consuming a web service that returns some XML data. The problems start when I convert the xml data to json. Some elements that are supposed to return an array of objects, when they have only one value, they are not converted to an array with a single object inside, they turn into an object. So instead of having:

{
"products":[ { "title":"Title 1",  "attributes":[{"color":"blue"}] } ]
}

I get

{
"products":{ "title":"Title 1", "attributes":{"color":"blue"} }
}

and the php array looks like this

[products] => Array ( [title] => Title 1 [attributes] => Array ( [color] => blue ) )

instead of this

[products] => Array ( [0] => Array ( [title] => Title 1
[attributes] => Array ([0] => Array ([color] => blue ) ) )

So what I have done is the below:

$xml = simplexml_load_string($messageData);
$json = json_encode($xml);
$array = json_decode($json, TRUE);

 if (isset($array['products']) && !isset($array['products'][0])) {
       $array['products'] = array($array['products']);
 } 

I check if there is an array named products and if it doesn’t have an index 0, I nest it inside a new array.
This does the job. Then I do the same for the attributes array like this:

    $products = $array['products'];

    $array['products'] = [];

    foreach ($products as $product) {

        if (isset($product['attributes']) && !isset($product['attributes'][0])) {

            $product['attributes'] = array($product['attributes']);

        }

        array_push($array['products'], product);
    }

Here, I bind the products array to a variable called products to use it in the loop, then I empty the array and after I create the new attributes array, I populate the products array with the changed products.

My question is:

Is there a better way to deal with this thing? I don’t like what I am doing here, but I can’t think of anything else…

EDIT

This is my soap request:


    $client = new SoapClient($wsdl, $soapOptions);

    $soapHeader = WsSecurity::createWsSecuritySoapHeader($username, $password, false, $synced, 60, true, true, false, true);

    $client->__setSoapHeaders($soapHeader);

    $response = $client->dateRetrieveMovement($dateMovementRequest);

    $movements = $response->DateMovementRequestResult->movements;
    $movementInfo = $movements->movementInfo;
    $messages = $movementInfo->messages->messageExchanged;

    $messageData = $messages->IEMessage->xmlData;

    $xml = simplexml_load_string($messageData);
    $json = json_encode($xml);
    $array = json_decode($json, TRUE);
How to&Answers:

The question is “is there a better way of doing the XML to JSON conversion”, and I think the answer is “not without doing some coding”.

Standard XML-to-JSON conversion libraries simply don’t know enough about the semantics of your data model to produce a decent representation of your data. In theory a tool could try an extract such information from a schema, or elsewhere, but I don’t know of any that does.

Writing a custom XSLT transformation to produce exactly the JSON you want is not too difficult, especially with XSLT 3.0, and this may well be less effort than patching up the JSON in the receiving application in the way you describe.