Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can we set a toJSON function to entities without effecting the way breeze js works? #197

Open
ofirgeller opened this issue Jul 1, 2017 · 5 comments

Comments

@ofirgeller
Copy link

If so, will this remain try in future versions?

The reason to do this is that when using redux it's much better if the state can be serialized, even if it's only a one way serialization. as it allows to inspect the state using tools like 'redux-devtools'. this however can only work if entities can be stringified, and as-is they can't be, my solution is to config the entity ctor like this

     this.metadataStore.registerEntityTypeCtor('MyEntityType', function () {
            this.toJSON = function () {
                return this._backingStore;
            };
        });

One can make this better to see more info like parts of the entity aspect, but this is the basic idea.

I would like to know if this will cause some hard to detect bugs inside of breeze or if it will break in future updates you are already planning.

@marcelgood
Copy link
Contributor

Well, generally you should never access private fields. Entities can be serialized using the exportEntities and importEntities methods.

this.metadataStore.registerEntityTypeCtor('MyEntityType', function () {
    this.toJSON = function () {
        return this.entityAspect.entityManager.exportEntities([this], { asString: false, includeMetadata: false });
    };
});

@ofirgeller
Copy link
Author

True that accessing private fields like _backingStore is a no-no, and if your way will return the same result I would use it. but I am way more concerned about the effect my code would have on breeze now/later than the effect a change in breeze will have on my code. if accessing _backingStore is broken in future updates that's no problem, I can just change my code to get the keys and values to serialize some other way, that's going to be a one line replaced with a few lines of code. If on the other hand overriding .toJSON breaks breeze I might have to re-write a lot of code so that I can stop keeping breeze entities inside of redux, that's a way bigger risk.

PS. If the risk is limited to losing breeze built in exporting/importing of a store that's something I can live with.

@marcelgood
Copy link
Contributor

Adding functions/methods to an entity is no problem. You can extend an entity that way to your heart's content.

@ofirgeller
Copy link
Author

This is not just some function.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior

This is why it might break other code that uses JSON.stringify on the entities is some way. but now that I think about it, since the reason i'm doing this to begin with is the fact that breeze entities cannot be serialized, I think I'm in the clear.

@marcelgood
Copy link
Contributor

Now I'm with you. I have never used the toJSON function. There is potentially a risk that in future versions we might use toJSON ourselves. Currently it doesn't. We have custom code in Breeze to serialize entities in order to send them over the wire and export/import them. The main issues with serializing entities is that they have circular references, so you can't just do JSON.stringify. You'll have to take control of the serialization with a filter function or handle the serialization yourself altogether, which is what Breeze is doing.

If you want to serialize an entity you can do so with breeze.core.toJSONSafe(obj, replacer). replacer is optional. If you leave it out it uses a default replacer.

// default replacer function for __toJSONSafe.  Excludes entityAspect and other internal properties
function __safeReplacer(prop, val) {
	if (prop === "entityAspect" || prop === "complexAspect" || prop === "entityType" || prop === "complexType"
	|| prop === "constructor" || prop.charAt(0) === '_' || prop.charAt(0) === '$') return;
	return val;
}

Sorry for the going around in circles on this one. It's been a while since I looked at the serialization in Breeze. The EntityQuery class in Breeze uses toJSON, that's the only place where it is currently used. Everything else goes through the toJSONSafe function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants