{"action":"created","issue":{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/3355","labels_url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/3355/labels{/name}","comments_url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/3355/comments","events_url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/3355/events","html_url":"https://github.com/pioneerspacesim/pioneer/pull/3355","id":58824489,"number":3355,"title":"JSONSerialise: migrating the save-game serialisation from a binary flat file to JSON","user":{"login":"nick-the-ninja","id":8797600,"avatar_url":"https://avatars.githubusercontent.com/u/8797600?v=3","gravatar_id":"","url":"https://api.github.com/users/nick-the-ninja","html_url":"https://github.com/nick-the-ninja","followers_url":"https://api.github.com/users/nick-the-ninja/followers","following_url":"https://api.github.com/users/nick-the-ninja/following{/other_user}","gists_url":"https://api.github.com/users/nick-the-ninja/gists{/gist_id}","starred_url":"https://api.github.com/users/nick-the-ninja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nick-the-ninja/subscriptions","organizations_url":"https://api.github.com/users/nick-the-ninja/orgs","repos_url":"https://api.github.com/users/nick-the-ninja/repos","events_url":"https://api.github.com/users/nick-the-ninja/events{/privacy}","received_events_url":"https://api.github.com/users/nick-the-ninja/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/labels/New%20feature","name":"New feature","color":"005000"},{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/labels/Savegame%20bump","name":"Savegame bump","color":"ff7fff"},{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/labels/WIP","name":"WIP","color":"444444"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":40,"created_at":"2015-02-24T23:33:47Z","updated_at":"2015-03-07T12:31:24Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/pulls/3355","html_url":"https://github.com/pioneerspacesim/pioneer/pull/3355","diff_url":"https://github.com/pioneerspacesim/pioneer/pull/3355.diff","patch_url":"https://github.com/pioneerspacesim/pioneer/pull/3355.patch"},"body":"The branch JSONSerialise contains the JSON serialisation code.\r\n\r\nThe JSON serialisation saves precisely the same data as the original serialisation. There is a one-to-one correspondance between the original and JSON serialisation code. Part of the review should be a cross-check between the two.\r\n\r\nThere are two new files: JsonUtils.h and JsonUtils.cpp\r\n\r\nEssentially, the relevant \"Serialize\" and \"Unserialize\" functions have been replaced by \"ToJson\" and \"FromJson\" functions. The relevant \"Save\" and \"Load\" functions have been replaced by \"SaveToJson\" and \"LoadFromJson\" functions. However, \"ModelSkin::Save\" and \"ModelSkin::Load\" are called by code other than the savegame process, so they remain (next to their corresponding \"SaveToJson\" and \"LoadFromJson\" functions).\r\n\r\nThe structure of the original serialisation code has been preserved. Relevant comments have also been carried over to the JSON serialisation code.\r\n\r\nAll JSON serialisation functions pass a reference to a JSON Value that is a JSON object. The only exception to this is \"Model::SaveToJson\" and \"Model::LoadFromJson\" where the SaveVisitor/LoadVisitor (now SaveVisitorJson/LoadVisitorJson) is passed a JSON Value that is a JSON array.\r\n\r\nThe save code typically passes a reference to the current JSON object into a function where other JSON objects and/or primitives are created and attached to the supplied object. Some serialisation functions are called recursively (as does the original serialisation).\r\n\r\nThe load code navigates the JSON tree as expected. All load functions begin by checking the contents of their supplied JSON object for appropriately named sub-objects/values. In the future, when the serialisation code has settled into a future-proof state, it is here that checks on missing objects can be put, and appropriate action taken for backwards compatibility.\r\n\r\nJSON arrays of objects are used as follows:\r\nWhen saving, the array is created and a loop entered, where for each iteration, an element object is created and passed into the JSON function which then populates it. The object is then appended to the array. Finally, when the loop is done, the array is added to the current object. The process can be easily followed.\r\n\r\nIssues to be addressed/considered:\r\n\r\n(1) Hexfloats\r\nI couldn't get them to work (see forum topic \"Hexfloats\"), so floats and doubles are saved by memcopying them to an int of the same size, then the int is saved. The reverse is done to load the float/double. Although the data suffers no loss of precision, this is not ideal because the data in the JSON save file is not human readable (although float 0.000000 is written as integer \"0\").\r\n\r\n(2) Lua data\r\nThis large string is not preserved when saved and loaded due to the non-printable characters at or near the end. The current solution is to save as a JSON array of integers (each integer is a char of the string). This works, but increases the size of the save file. The data is also not human readable.\r\n\r\n(3) #include \"Serialiser.h\"\r\nThese remain, because the JSON serialisation code uses the exceptions. Perhaps the exceptions should be moved? Other code may also require functions declared in \"Serialiser.h\".\r\n\r\nI have come across issues that (for me) also occur in pioneer from upstream. Please check this is not the case before flagging the issue as a JSONSerialise bug :)\r\n\r\nThanks :)\r\nNick"},"comment":{"url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/comments/77687489","html_url":"https://github.com/pioneerspacesim/pioneer/pull/3355#issuecomment-77687489","issue_url":"https://api.github.com/repos/pioneerspacesim/pioneer/issues/3355","id":77687489,"user":{"login":"walterar","id":1334989,"avatar_url":"https://avatars.githubusercontent.com/u/1334989?v=3","gravatar_id":"","url":"https://api.github.com/users/walterar","html_url":"https://github.com/walterar","followers_url":"https://api.github.com/users/walterar/followers","following_url":"https://api.github.com/users/walterar/following{/other_user}","gists_url":"https://api.github.com/users/walterar/gists{/gist_id}","starred_url":"https://api.github.com/users/walterar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/walterar/subscriptions","organizations_url":"https://api.github.com/users/walterar/orgs","repos_url":"https://api.github.com/users/walterar/repos","events_url":"https://api.github.com/users/walterar/events{/privacy}","received_events_url":"https://api.github.com/users/walterar/received_events","type":"User","site_admin":false},"created_at":"2015-03-07T12:31:24Z","updated_at":"2015-03-07T12:31:24Z","body":"After many hours of play, I did not find any problems after applying this PR.\r\nNor was repeated #3345. I wonder if this fixed it, or is it a coincidence"}}