Good practices in an API Wrapper Class i'm trying to build an API wrapper class, that sends requests in a JSON format. the sample request format is something like this:

{
  "items": [
    {
      "brand": "brand",
      "idCategory": "idCategory",
      "idItem": "idItem",
      "attributes": [
        {
          "idUda": "idUda",
          "price": "price"
        },
        {
          "idUda": "idUda",
          "price": "price"
        }
      ],
      "description": "description",
      "skus": [
        {
          "price": {
            "offer": "offer",
            "default": "default"
          },
          "stock": {
            "available": "available",
            "amount": "amount"
          },
          "gtin": "gtin",
          "images": [
            "image",
            "image"
          ],
          "idSku": "idSku",
        }
      ]
    }
  ]
}


my first thought was to create an object for each element of the JSON request that is an array, something like this:

        $attr1 = new Attribute;
        $attr1-&gt;setIdUda('xxx')
        -&gt;setPrice('99999');

        $price = new Price;
        $price-&gt;setOffer('teste')
        -&gt;setDefault('99.99');

        $stock = new Stock;
        $stock-&gt;setAvailable(true)
        -&gt;setAmount('9999');

        $product = new Product;
        $product-&gt;setBrand('Apple')
        -&gt;setIdCategory('500')
        -&gt;setIdItem('9999')
        -&gt;setAttributes($attr1)
        -&gt;setDescription('nice product')
        -&gt;setSkus($price);
        -&gt;setSkus($stock);


and each one these objects have a toArray() method, that returns an associative array, eg:

class Price {

        //getters and setters....

            function toArray() {
                return array(
                    'offer' =&gt; $this-&gt;offer,
                    'default' =&gt; $this-&gt;default
                )
            }
        }


inside of the Product class all these attributes setters are grouped to form an array so i can convert it to the JSON format later.

class Product {
        //..... 
    public function setAttributes(Attribute $attributes) {

        $this-&gt;attributes['attributes'][] = $attributes-&gt;toArray();
                    return $this;
    }
}


but it still feels like it's highly coupled, because i have to set the key of each one of these arrays, in order to form the JSON data.

What would be the "best" approach to make this code easier to maintain? should i use classes only for some attributes? how should i consider it?
There is no problem modelling the request with classes representing each part of the request and a class that aggregates them.

One thing to note here, those classes adhere to builder pattern - builder of JSON.
Maybe you dont know that there is an interface \JsonSerializable which would comminucate the intent of the classes much better then a toArray() method. Although many arrays can be deemd json serializable, its not always true. Where as json serializable object is always serializable to json and it makes it clear that the json serializability is its purpose...

Then i quite dont understand this piece:

        $product
        -&gt;setSkus($price);
        -&gt;setSkus($stock);


You set skus to a Price object, then overwrite with Stock object?
Given this piece of data:

"skus": [
        {
          "price": {
            "offer": "offer",
            "default": "default"
          },
          "stock": {
            "available": "available",
            "amount": "amount"
          },
          "gtin": "gtin",
          "images": [
            "image",
            "image"
          ],
          "idSku": "idSku",
        }
      ]


I would expect that there is one more object between Product and Stock/Price object. Maybe a Sku object:

$product-&gt;addSku((new Sku())-&gt;setPrice($price)-&gt;setStock($stock));


And I wouldnt also see problem adding methods for more convenient work (that would instantiate the parts classes):

$sku = new Sku();
$sku-&gt;setPrice('offer', 'default');
$sku-&gt;setStock('available', 'amount')


instead of:

$sku = new Sku();
$sku-&gt;setPrice(new Price('offer', 'default'));
$sku-&gt;setStock(new Stock('available', 'amount'));


After all, those classes are not meant to represent the request, they represent a builder of a json request. And builder should make it as easy to build the target as possible....

EDIT: you were worried about coupling. I dont think this brings in any more coupling then necesary. The API uses specific keys in the request and these will never change, unless the API introduces BC break. But then maybe it was not a very good API structure... Anyway it wouldnt hurt to have those keys defined as constants of the bulder classes, so you dont have to repeat string literals all over the place... if nothing it makes it easier to find all occurences of a key.

Chances are that there are multiple ways the api could have been designed, yet retaining the same capabilities. And this means that there are also multiple ways to model the request with php objects. But you should prefer to have this 1:1. The api designer was probably aware of the multiple ways and chosen the one he chosen for a reason. And you should follow that reasoning...

Well this statement might have seem quite abstract, so let me complete it with an example. Lets say we have api structure:

{
  "scopeA": {
    "configA1": "valueA1"
  },
  "scopeB": {
    "configB1": "valueB1"
  }
}


but we can also model it as this structure:

{
  "scopeAconfigA1": "valueA1",
  "scopeBconfigB1": "valueB1"
}


but the first structure is the API structure, and so the PHP model should also have the first structure. Simply following the same reasoning why the api designers chose the first structure. Whatever reasoning it may have been...