Coder Social home page Coder Social logo

nilportugues / php-json-api Goto Github PK

View Code? Open in Web Editor NEW
71.0 7.0 36.0 639 KB

JSON API transformer outputting valid (PSR-7) API Responses.

Home Page: http://nilportugues.com

License: MIT License

PHP 100.00%
json-api json transformer marshaller serialization serializer api microservice microservices php

php-json-api's People

Contributors

alexjoffroy avatar basz avatar dunglas avatar franbenz avatar gsokol avatar hainovsky avatar hennerm avatar javiacei avatar jeremymlane avatar kgeiger-godaddy avatar m1n0 avatar nilportugues avatar oskard avatar raplider avatar rruizdiaz avatar suslin avatar tybulewicz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-json-api's Issues

JSONAPI - Relationship

Get from "included" objects the relationship and append it to its parent.

In the provided example, comments from "included" should be in post's relationship.

This requires all classes to implement or have an add relationship method to construct the URI to the resource.

Allow pagination and meta for all serializers

Actually only JSONAPI and HALJSON serializer are meant to support these, but JSON could support it too by adding a meta attribute holding these.

$serializer->setSelfUrl('http://example.com/posts/9');
$serializer->setNextUrl('http://example.com/posts/10');
$serializer->addMeta(
  'author',
  [
    ['name' => 'Nil Portugués Calderó', 'email' => '[email protected]']
  ]
);

JSONAPI - Allow Filter value's keys

Output filtering is required to be done before transformation, but right after the key underscoring and the key aliasing.

This will be used when a URL contains ?filter[value]=key1,key2

[Insight] Unused method, property, variable or parameter - in src/Server/Data/DataObject.php, line 198

in src/Server/Data/DataObject.php, line 198

This errorBag local variable is declared but never used. You should remove it.

                $mapping->getProperties()
            );

            foreach (array_keys($relationshipData[JsonApiTransformer::ATTRIBUTES_KEY]) as $property) {
                if (false === in_array($property, $properties, true)) {
                    $errorBag[] = new InvalidAttributeError($property, $relationshipData[JsonApiTransformer::TYPE_KEY]);
                }
            }
        }
    }
}

Posted from SensioLabsInsight

JSONAPI - Allow hidding attributes

Pass the name of the attributes to hide.

Hiding attributes can make relationships and includes not to show up as data hidden will be not parsed or transformed.

Resource creation doesn't comply with the spec

Bug for https://github.com/nilportugues/jsonapi-transformer/blob/master/src/Http/Message/ResourceCreatedResponse.php

✅ If a POST request did not include a Client-Generated ID and the requested resource has been created successfully, the server MUST return a 201 Created status code.

🔴 The response SHOULD include a Location header identifying the location of the newly created resource.

🔴 The response MUST also include a document that contains the primary resource created.

🔴 If the resource object returned by the response contains a self key in its links member and a Location header is provided, the value of the self member MUST match the value of the Location header.

HTTP/1.1 201 Created
Location: http://example.com/photos/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/vnd.api+json
{
  "data": {
    "type": "photos",
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "links": {
      "self": "http://example.com/photos/550e8400-e29b-41d4-a716-446655440000"
    }
  }
}

Naming convention of data attributes keys

According to the JSON recommendation (http://jsonapi.org/recommendations/#naming) the preferred naming convention is to use hyphens to separate words in keys, eg 'modified-date'. Current implementation of the library has a dependency on nilportugues/php-api-transformer which converts camelCase words to underscore-separated words, eg: 'modifiedDate' to 'modified_date', which leaves no way to conform to the recommendation. It would be great to add an option that allows to choose which transformation logic is applied to the key names.

Id Field Aliasing

I have domain model with uuid field and want use it as id value for API mapping.

I put uuid to getIdProperties, it is work fine for set id and links values in json.
But I see uuid in attributes:

Failed asserting that '{"data":{"type":"some_model","id":"foo-bar","attributes":{"name":"foo","uuid":"foo-bar"},"links":{"self":{"href":"/api/v1/some-models/foo-bar"}}},"links":{"self":{"href":"/api/v1/some-models/foo-bar"}},"jsonapi":{"version":"1.0"}}' matches JSON string "{
    "data": {
        "type": "some_model",
        "id": "foo-bar",
        "attributes": {
            "name": "foo"
        },
        "links": {
            "self": {
                "href": "/api/v1/some-models/foo-bar"        
            }
        }
    },
    "links": {
        "self": {
            "href": "/api/v1/some-models/foo-bar"        
        }
    },
    "jsonapi": {
        "version": "1.0"
    }
}".
--- Expected
+++ Actual
@@ @@
         "type": "some_model",
         "id": "foo-bar",
         "attributes": {
-            "name": "foo"
+            "name": "foo",
+            "uuid": "foo-bar"
         },
         "links": {
             "self": {

I try hide this property and use aliases, but I could not succeed with my case.
I create repo with example:
https://github.com/samizdam/jsonapi-example/blob/master/tests/Samizdam/JsonApiExampleTest/ModelWithUuidMappingTest.php

Q: doctrine usage

I see this library supports doctrine entities as input to the serialiser.

https://github.com/nilportugues/php-json-api/blob/aa305a4ea7a9aef0be3cf243c1e2cf3c9efb3411/tests/Integrations/Doctrine/DoctrineTest.php

That example works without relationships. It seems I get into an infinite loop when I have two entities referencing each other.

identity has many preferences.

So either I am doing something wrong, perhaps I should not fetch eager or something. Or this is not possible with this library or I might have found a bug...

https://gist.github.com/basz/898f6981ac12a6a43c3edc19d607a29c

I have pinned it down to the serialiser::serializeData method in the serializer.

URL generation should attempt to use id value from class/alias if translation failed

Hard title, easy to explain.

Given a mapping User, with name user as the type in the response, and a url template being /user/{user}/edit... mapping to the id field (that being a class property named id or user_id) will fail.

Yet, it is possible to guess that is the type is user, and user is in the url, the value should be the id's, as we are following a convention.

This should be done as a second pass, after applying the id fields for the URL generation and getting the same result and before disregarding the URL.

Validation and Hidden Fields

If I had the following validation rule

protected $rules = [
    'password'  =>  'required|valid_password|min:8'
];

And if I wished to hide that field from the response

protected $hidden = ['password'];

My password setter is:

public function setPasswordAttribute($value)
{
    $validator = \Validator::make(['password'=>$value], $this->getRules(), $this->getMessages());

    if ($validator->fails()) {
        $this->attributes['password'] = $value;
        return $this;
    }

    $this->attributes['password'] = password_hash($value, PASSWORD_BCRYPT);

    return $this;
}

Then when testing this functionality with the following

$user = new User();
$user->password = 'xxx'

$user->isValid();

dd($user->getErrors());

I get the following error

Illuminate\Support\MessageBag {#328
    #messages: array:1 [
        "password" => array:1 [
            0 => "The password field is required."
        ]
     ]
     #format: ":message"
 }

If I comment out the

protected $hidden = ['password'];

Everything works as expected

:-)

Deeply nested array of objects

Currently travelling but will give proper example when back home on PC.

Basically, post with many comments is ok but post with many comments each with many replies fails.

hiddenFields exposed in relationships

Given two DTO's (Identity and Preference) where Identity has a hidden field passwordHash.

I noticed that when I serialize the Identity DTO the passwordHash field is correctly hidden.

But when I serialize Preference with a relationship to to Identity the passwordHash is not hidden.

{
  "data": {
    "type": "identity/preference",
    "id": "212dca7d-87be-500f-a269-0ddef0757415",
    "attributes": {
      "name": "restriction.ip.enabled",
      "preference_id": "212dca7d-87be-500f-a269-0ddef0757415",
      "value": false
    },
    "relationships": {
      "identity": {
        "data": {
          "type": "identity/user",
          "id": "fff1324d-1383-5363-a6db-b9b7d2f856e9"
        }
      }
    }
  },
  "included": [
    {
      "type": "identity/user",
      "id": "fff1324d-1383-5363-a6db-b9b7d2f856e9",
      "attributes": {
        "passwordHash": "$2y$14$Q0xLWS....",
        "displayName": "Xxxxx Xx Xxx",
        "emailAddress": "[email protected]",
        "registrationDate": "2012-12-20T13:41:29+0100",
        "emailStatus": "verified",
        "accountStatus": "active",
        "roles": [
          "guest",
          "member",
          "admin",
          "member.customer"
        ]
      }
    }
  ],
  "jsonapi": {
    "version": "1.0"
  }
}

MappingFactory::fromArray() always seems to unbox the array

I am constantly getting for this code:

    $mappings = array(OfferMapping::class); // Also tried with []
   

    $mapper = new Mapper($mappings);
    $transformer = new JsonApiTransformer($mapper);
    $serializer = new JsonApiSerializer($transformer);
		return response()->$serializer->serialize(Offer::all())
                     ->header('Access-Control-Allow-Origin', '*');

This error message:

1/1
FatalThrowableError in MappingFactory.php line 93:
Type error: Argument 1 passed to NilPortugues\Api\Mapping\MappingFactory::fromArray() must be of the type array, string given, called in /var/www/vendor/nilportugues/api-transformer/src/Mapping/Mapper.php on line 53
in MappingFactory.php line 93
at MappingFactory::fromArray('App\Api\Mappings\OfferMapping') in Mapper.php line 53
at Mapper->buildMapping('App\Api\Mappings\OfferMapping') in Mapper.php line 36
at Mapper->__construct(array('App\Api\Mappings\OfferMapping')) in OfferController.php line 35

I have tried passing

 $mapper = new Mapper([1]);
 $mapper = new Mapper(array(OfferMapping::class, $othermapping))

And other example values with no result. It seems to internally unbox the first one all the time.

I am using laravel 5.2 and using php-json-api 2.6.0.

Sample code for bundling

Just the concept. Needs work

//To build a bundle we need to automate generating the array with postId => {postId}
$routeNameFromMappingFile = 'nilportugues_application_view_post';

$router = $this->get('router')->getRouteCollection()->get($routeNameFromMappingFile);
preg_match_all('/{(.*?)}/', $router->getPath(), $matches);

$pattern = [];
if(!empty($matches)) {
    $pattern = array_combine($matches[1], $matches[0]);
}

$route = urldecode($this->generateUrl($routeNameFromMappingFile, $pattern, true));


//Mapping declaration
$mapping = new Mapping(ViewPostResponse::class, $route, ['postId']);
$mapping->setClassAlias('post');
$mapping->setPropertyNameAliases(['postTitle' => 'headline', 'postBody' => 'content']);
$mappings = [$mapping->getClassName() => $mapping];

//Serializer into action
$serializer = new Serializer(new JsonApiTransformer($mappings));
$response = $serializer->serialize($commandBus->getResult());


return new Response(
$response, 200, ['Content-type' => 'application/vnd.api+json; charset=utf-8']));

[Insight] Unused method, property, variable or parameter - in src/Server/Data/DataAssertions.php, line 131

in src/Server/Data/DataAssertions.php, line 131

This errorBag local variable is declared but never used. You should remove it.

        $hasErrors = false;
        foreach ($inputAttributes as $property) {
            if (false === in_array($property, $properties)) {
                $hasErrors = true;
                $errorBag[] = new InvalidAttributeError($property, $data[JsonApiTransformer::TYPE_KEY]);
            }
        }

        if ($hasErrors) {
            throw new DataException();

Posted from SensioLabsInsight

Add Inflectors

Having a property named "article", if it's a collection returning an array, should be renamed to "articles".

Inflectors should be defined prior to the transformation

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.