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

Make inst2dict and dict2inst work recursively #33137

Closed
wants to merge 1 commit into from
Closed

Make inst2dict and dict2inst work recursively #33137

wants to merge 1 commit into from

Conversation

Xrayez
Copy link
Contributor

@Xrayez Xrayez commented Oct 28, 2019

Closes #6533.

This makes inst2dict GDScript method to turn inner instances present as properties to be converted to a dictionary recursively, including instances with nested arrays and dictionaries with key/value pair.

Added a deep paramater to inst2dict so that the default behavior remains the same. Recursive conversion is disabled by default because instances may have circular references as described in #31229 (comment), hence must be used with caution on case-to-case basis. Updated documentation accordingly.

Features

  • Convert properties with instances (inner classes) recursively using inst2dict.
  • Convert nested arrays with classes recursively using inst2dict.
  • Convert nested dictionaries with classes recursively.
  • Convert all back using dict2inst (all above).
  • Add recursive/deep option for inst2dict method.

Test project

Extensive test project demonstrating all of the added features, and showing how having circular references fail, which is handled in debug builds by checking that only unique objects are converted.

inst2dict-recursive.zip

@Xrayez
Copy link
Contributor Author

Xrayez commented Oct 29, 2019

While testing serialization features with:

var json = to_json(inst2dict(inst, true)) # recursive
var inst = dict2inst(parse_json(json))

I stumbled upon serialization "bug" pertaining to JSON parsing dictionary keys as described in #33161. If this feature gets merged then it certainly must be fixed.

@Xrayez Xrayez marked this pull request as ready for review October 29, 2019 14:30
@Xrayez
Copy link
Contributor Author

Xrayez commented Oct 29, 2019

An alternative fix is to not turn dictionary keys (which can be object instances) into "dictionary instances" as seen in:

for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
	// Both key and value can be objects
	Variant vi = _inst_to_dict_or_var(dict[E->get()], r_error, p_deep);
	// Variant ki = _inst_to_dict_or_var(E->get(), r_error, p_deep); // do not support it?
	Variant ki = E->get()
	ret_dict[ki] = vi;
}

But these can lead to unexpected serialization issues. Or just add explicit error check and call it a feature.

@akien-mga akien-mga added this to the 3.2 milestone Nov 7, 2019
@akien-mga akien-mga modified the milestones: 3.2, 4.0 Nov 21, 2019
@Xrayez
Copy link
Contributor Author

Xrayez commented May 31, 2020

Note: this was initially developed for/against 3.2 and was well tested there at the time of writing (see test project).

@vnen given there was a "duplicate" PR fixing the same issue (#38377), I wonder what would be a good time to make this PR work against current 4.0 master branch, and whether this could be backported to 3.2 once available in master (if the feature is desired at all).

@Xrayez Xrayez changed the title Make inst2dict and dict2inst work recursively [3.2] Make inst2dict and dict2inst work recursively May 31, 2020
@Xrayez Xrayez changed the base branch from master to 3.2 May 31, 2020 22:14
@Xrayez Xrayez changed the base branch from 3.2 to master May 31, 2020 22:15
@Xrayez Xrayez changed the title [3.2] Make inst2dict and dict2inst work recursively Make inst2dict and dict2inst work recursively May 31, 2020
This makes `inst2dict` GDScript method to turn inner instances present
as properties to be converted to dictionaries recursively, including
instances with nested arrays and dictionaries with key/value pair.

Added a `deep` paramater to `inst2dict` so that the default behavior
remains the same. Recursive conversion is disabled by default because
instances may have circular references, hence must be used with caution
on case-to-case basis. Crashes prevented by detecting circular references
in debug builds. Updated documentation accordingly.
@Xrayez
Copy link
Contributor Author

Xrayez commented Jul 6, 2020

Rebased, but the test project fails now in current master f8c066e, will need to investigate further... This worked fine in 3.2, not sure what could change since that time.

This is probably related to broken dictionaries as described in the similar the PR #38377 by @ThakeeNathees, but I'm not sure. Somehow, all the properties get converted to null on dict2inst, while inst2dict works fine 😕.

Not sure whether I'm motivated enough to make this work, and it would likely be safer to redo this from anew against master branch anyways to make sure that the rebase didn't lose the previous smaller fixes as seen in the tracker: #33348 (too many delete/add code due to moving implementation to methods), so I better close this.

In fact, I don't mind if @ThakeeNathees could get some insights from this PR, take both test projects and see how this can be improved, the idea is pre-approved by @vnen (IRC log):

vnen> Xrayez: I think the idea is fine, though it should be reviewed. On a quick glance it looks fine. If you fix the conflicts we can review and merge

If there's still no work done by any of the potential contributor, I might return to this when I'll actually need this feature myself.

I've saved the original branch which was originally targeted for 3.2: https://github.com/Xrayez/godot/commit/9ea46abcc42b000776f5c5a5d1487fae4d10db06.

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

Successfully merging this pull request may close these issues.

inst2dict does not turn classes inside classes to dict
2 participants