Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
serialization.module
Priority:
Major
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
18 Jan 2013 at 14:51 UTC
Updated:
2 Mar 2015 at 03:49 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
damiankloip commentedI will work on this on my train journey.
Comment #2
Anonymous (not verified) commentedWe may need to add bundle to the normalized output in order to determine the bundle on deserialization.
Comment #3
damiankloip commentedJust posting some general progress from yesterday. Please don't take it too seriously.
I have refactored the NormalizerBase class a bit, and added some conditional stuff to it do do with format, so it can be used both generically and extended for particular formats. Not sure if this is the right approach yet though.
At the moment I tihnk I've got an abstract EntityNormalizer class, not sure we will need that either.
Comment #4
damiankloip commentedSo a bit more like this, I should have more time later to do something more concrete.
Comment #5
damiankloip commentedSomething more like this?
Comment #7
damiankloip commentedThis should fix those failures.
Comment #9
damiankloip commentedI wasn't actually using the checkFormat method :) Doh. This should now pass fine. So, from here we are in a better position to review and decide on our path.
Comment #10
podarok#9: 1892320-9.patch queued for re-testing.
Comment #12
Anonymous (not verified) commentedI'm sorry I don't have a review for you :( ....but at least I have a shiny new component.
Comment #13
damiankloip commentedRerolled after #1903784: Move serialization to own module. I will need to change the namespaces etc... will do that when I have some time shortly.
Comment #15
damiankloip commentedProper re roll.
Comment #17
damiankloip commentedOops missed the json ld normalizer base.
Comment #18
damiankloip commentedRerolled after the unit tests and lin's patch changing the static property, as this patch made that change too.
Comment #20
damiankloip commentedBroke JsonldNormalizerBase class, it wants to extend the new base class I created instead.
Comment #21
Anonymous (not verified) commentedFYI, there is a patch to remove JSON-LD module, so we don't need to include changes to that.
The denormalizer should use a recursive workflow, just as the normalizer does. This allows for fine grained handling of fields by their field item class. You can see an example of that in #1931976: Support deserialization for hal+json (needs more language handling tests). It's probably worth waiting until that work is committed because this patch can reuse a lot from that.
Comment #22
damiankloip commentedOK, let's postpone on that one.
Comment #23
damiankloip commentedThe main hal patch is in, so let's get this one back on the road. This is just a reroll removing the jsonld changes, and adding the changes to hal classes instead. This doesn't yet add any of the recursive stuff.
Comment #24
Anonymous (not verified) commentedI think it would be worth waiting until the work on hal+json is totally done (which it isn't quite yet). There's a lot of details that will get worked out as a part of that process, and it will be easier to just copy them to this patch as opposed to keeping the two approaches in sync.
Comment #25
Anonymous (not verified) commentedJust to note it for later...
The bundle should also be included. Additionally, it would be worth testing that the created entity is an instance of the expected class.
-3 days to next Drupal core point release.
Comment #26
damiankloip commentedReroll without the conversion of $formats property from static and array. I think we should consider Just casting in the base class, see NormalizerBase::checkFormat() in this patch.
So yeah, I guess we want to work out exactly what we want to include in this patch, and how far entity NG stuff actually is.
Comment #29
damiankloip commentedMeh, I think it makes sense to cast these values to an array. We can then support both a single class string and an array of class/interface names.
I also added some logic to deal with the bundle and some assertions to test the denormalization. I have changed the keys that get normalized to '_entity_type' and '_bundle', to me this makes sense as it signifies it is a key that is dealt with by the serializer.
What do you think?
Comment #30
Anonymous (not verified) commentedIs there a reason that this was changed to an underscore? Also, why an underscore and not some other marker. Nothing wrong with it, but just wondering the rationale.
Here, you cast inside the array_filter, but in supportsDenormalization, you cast in a variable outside. I think both should be cast in a variable outside of the array_filter call.
Comment #31
damiankloip commentedI thought I'd go with the underscore to separate it out from regular entity props. Mainly for bundle, as the bundle key can change depending on the entity, so thought it easier to just always have a consistent _bundle in the normalized data. So thought I would change both. What do you think?
Comment #32
damiankloip commentedSorry, mixed another random patch in #31, interdiff is still ok.
Comment #33
dawehnerIt seems to make sense to have a better classname which supports both Decoding and encoding?
@inheritdoc
Let's explain when the exception is thrown.
Do you always want to require the bundle data, even if the entity type does not use bundles?
Just do return !(isset($format) && isset($this->format)) etc.
Just wondering about the priority of one.
Comment #34
damiankloip commentedThe standard seems to just be to use *Encoder for this, so not sure. We would maybe have to change all other in that case.
Yeah, prob not needed as the default order of the services in the container will be honoured.
I think I've addressed the other points. I've moved the exception for no '_bundle' key only if the entity type supports bundles. I think that is better?
Comment #35
Anonymous (not verified) commentedAgreed that it is better to limit the exception to cases where the entity supports bundles. However, I think we might want to consider changing it from using _bundle as the key to using the actual key name. I don't feel strongly about it, but it would be worth getting opinions from others.
Comment #36
dawehnerFoe access controllers we use entity_type.bundle_name, what about using the same kind of pattern here as well? If the bundle_name is optional just drop it.
Comment #37
Crell commentedWe discussed this issue on the REST team meeting today. The general consensus was that application/json is understood as a Drupal-specific format where you are presumed to have prior knowledge of what you'll be getting back, which means we should be using the easier-to-serialize/deserialize raw value, not _bundle.
Comment #38
effulgentsia commentedI was on the call that #37 refers to, and agree that we shouldn't need _bundle. Also, I don't see why we need _entity_type in the data: shouldn't that be in the $context instead, when deserializing? E.g., if deserialization is triggered from rest.module, the URI defines the entity type; if it's triggered some other way, whatever that way is should know the entity type and pass that in.
Also, what is the use case we're adding deserialization of json for to begin with? Client-side apps (backbone or phone) are probably better off with HAL. On our call, we identified migrate/deploy as the most likely good use case for round tripping straight json, but for that we need #2060677: Add target_type, target_uuid to serialized output of entity reference fields in non-HAL formats.
Comment #39
damiankloip commentedIts a good point about the entity type, we should have that from the context. However, I think having the bundle is totally valid. You would pass that into entity_create anyway? So we should have that.
It seems totally incomplete to not be able to consume json IMO. People could use this for their own web services a lot. I don't think we need to wait for that issue here either?
Comment #40
effulgentsia commentedBut you don't pass _bundle into entity_create(). If you're creating a node, you call
entity_create('node', array('type' => 'article', ...))and if you're creating a taxonomy term, you callentity_create('taxonomy_term', array('vid' => 'tags', ...)). So we don't need_bundleas a special extra key in the serialized output; the 'type', 'vid', or whatever other key is the bundle key is already in the output and entity_create() knows how to deal with it.Comment #41
effulgentsia commentedI'm ok with proceeding with this issue independantly of #2060677: Add target_type, target_uuid to serialized output of entity reference fields in non-HAL formats, just to keep the scope of each issue well focused. But I'm also curious if anyone here can think of a use case where deserializing json containing ER fields, without uuids on those fields, would ever make sense.
Comment #42
damiankloip commentedSorry, I wasn't clear before, I'm talking about changing the bundle key back to its original key, and not using _bundle at all. I know entity_create will not know what to do with _bundle :)
Why would every case have to depend on an entity reference field? I don't see how that's a requirement for serializing/unserializing stuff.
We should also consider handling the bundle property in entityNG the same as other properties. Currently, because the bundle get's passed into the entityNG constructor this has to be a raw value, and not a nested array like everything else.
Comment #43
damiankloip commentedSorry, forgot to change the tests too.
Comment #44
dawehnerDon't we have the entity_manager already as local variable? Maybe it is worth to switch here to an injected version but I don't care that much.
Comment #45
damiankloip commentedYep, I forgot to change that! We could go with the setter approach, as that Lin started using that in some of the hal stuff.
Comment #47
damiankloip commented#45: 1892320-45.patch queued for re-testing.
Comment #48
dawehnerI don't see the advantage of using a setter than just constructor based dependency injection ... can you please clarify why?
Comment #49
damiankloip commentedErrm, nope :) No reason beyond bringing it inline with what we have already.
I prefer constructor injection, If anything maybe other serializer related classes should all make sure they do this too?
Comment #50
dawehnerYou are the man of empty patches today!
Comment #51
damiankloip commentedHA, yes I am! I'm not sure what's happening to me...
interdiff in #49 is still good.
EDIT: Something is going wrong with file uploads. This patch I am looking at definitely has stuff in!!
Comment #52
damiankloip commentedComment #53
dawehnerSo we use Implements if something additional is done than we can cover by @inheritdoc?
Is there a reason why we can't just do $data[$bundle_key] = $type and skip the unsetting?
That is kind of odd :(
Comment #54
Anonymous (not verified) commentedConstructor injection seems fine for this case.
This is a rather long and complicated conditional. Can we possibly move the checks to variables that communicate what they are checking?
I haven't been keeping up, so this might be the preferred way to do things these days... but entity_create seems a lot clearer to me and it doesn't look like it is deprecated.
Also, if we're switching to add an EntityNormalizer, we should remove whichever normalizer was handling things at the entity level before. Otherwise we create too many potential code paths.
Leaving at needs review so tests can run.
Comment #55
damiankloip commentedYes, at the moment the comment is like this for the @throws part.
Yes, I guess it is a bit but I'm not sure where else this could live.
Comment #56
damiankloip commentedSorry Lin, I think I totally missed your review there, I think I posted the patch before updating this issue.
Fair point, there was some eye bleeding stuff in there; I have refactored checkFormat() to be much easier to read, as that was doing some double false positive logic, which is not easy for anyone to read. I have also moved the callables that were being used in the array_filter checks to variables. This should make it both easier to read and self documents what the check is.
Before it was using the ComplexDataNormalizer, which I think we should keep really?
Comment #57
damiankloip commentedRolled and made a few changes to the logic in the NormalizerBase class.
Comment #58
dawehnerWhat about using @inheritdoc here?
I am wondering whether is_subclass_of just works here as well.
We switched to entity.manager quite a while ago.
Comment #60
damiankloip commentedThank you! Also, the test was failing as the old patch still had EntityNG, which doesn't exist anymore :)
Comment #61
dawehnerThat one is still in.
Comment #62
damiankloip commentedI think we want to keep that comment tbh.
Comment #63
Anonymous (not verified) commentedI'm not sure why we would want to keep the ComplexDataNormalizer.
Comment #64
berdirAre we doing this in multiple places?
Seems like create()/the upcoming entity factory should better support this by default and not require custom code here.
Also, there's a third option to consider, another level, keyed by the language code, which is how the values are coming from the database for example.
That again reminds me, how is serialization + entity translations going to work? Seems like everything should either be for a specific language and define that (then it needs to handle per-language changes correctly) or return/accept all languages somehow..
Comment #65
damiankloip commentedI think just here. The entity dernormalization in hal module does something a bit different. If this gets fixed in entities in general, happy to change this too :)
Also, regarding the translations, this is also down to the entities, as we are just creating instances with the data. Do these need separate issues?
This issue is still good to go IMO.
Comment #66
damiankloip commentedLin, I think the ComplexDataNormalizer will serve as a good base implementation anyway? But this is used by content entities and field items, so most things are covered I guess.
I vote it stays :)
Comment #67
dawehner60: 1892320-60.patch queued for re-testing.
Comment #68
damiankloip commented60: 1892320-60.patch queued for re-testing.
Comment #70
damiankloip commentedRerolled and made the EntityType class changes.
Comment #71
dawehnerSorry for my review.
We do have interfaces for that.
Are you sure we should not use some interfaces?
Comment #72
damiankloip commentedYes, and yes!
Comment #73
dawehnerSo could we?
Comment #74
damiankloip commentedYes we can :) I'll reroll in the morning.
Comment #75
damiankloip commentedSorry, forgot about this one!
Comment #76
dawehnerThank you!
Comment #77
damiankloip commentedbumping to major, this is incomplete functionality. As well as people building stuff on REST, consuming JSON will probably be the most common implementation of that.
Comment #78
damiankloip commentedbumping to major, this is incomplete functionality.
As well as people building stuff on REST; consuming JSON will probably be the most common implementation of that.
Comment #79
webchickAgreed with this being major. It'd also be great to have in the next alpha release, so folks can continue testing the new REST functionality in Drupal 8.
I looked through and couldn't see anything to complain about. Stuff is tested, documented, etc. Great!
Committed and pushed to 8.x. Thanks!
Comment #81
davidwbarratt commentedWhenever you try to deserialize a ContentEntity, you get this error:
The code responsible for that error is here:
Since the code assumes that the bundle is in
valuekey rather than thetarget_idkey a ContentEntity cannot be deserialized.I've opened #2443165: Drupal\Core\Entity\EntityInterface\ContentEntityStorageBase::doCreate() assumes that the bundle is a string to fix the problem. :)