- Изменено
"Invalid skeleton JSON" with trial .json file and runtimes
I'm currently evaluating spine and have downloaded the spine trial which also comes with some exported image/skeleton/animation data. When trying to use the exported 'spineboy-ess.json' file from the latest 3.7 spine beta trial version with the latest spine-c runtimes I keep getting an "Invalid skeleton JSON" error when coding. The code I'm using is this (in C++ application):
spAtlas* atlas = spAtlas_createFromFile("spineboy.atlas", 0);
RUNTIME_ASSERT(atlas != nullptr, "Atlas not loading properly!");
spSkeletonJson* json = spSkeletonJson_create(atlas);
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonData(json, "spineboy-ess.json");
if (!skeletonData)
{
LOG("%s\n", json->error);
spSkeletonJson_dispose(json);
};
As you may have noticed the issue comes with the skeletonData being null (thus meaning the .json isn't loading properly). I have tried the 3.6 version of the runtimes as well to no avail. Is this an issue with the trial exported .json file? I attached it to this post as well.
I'm having troubles reproducing this. I've tried loading the spineboy-ess.json you attached in the spine-sfml demos as well as the spine-cocos2dx demos, using the 3.6 spine-runtimes and 3.7-beta spine-runtimes branch, but it loaded fine. Your code also looks fine. Could you debug into spSkeletonJson_readSkeleton and see where it fails?
FWIW, the examples in the Spine runtime repository and the ones shipped with Spine Trial/ESS/PRO/ENT are the same, so there shouldn't be any issue.
After debugging a bit, it seems the error is occuring within the 'Json_create(const char* value)' function:
/* Parse an object - create a new root, and populate. */
Json Json_create (const char value) {
Json c;
ep = 0;
if (!value) return 0; / only place we check for NULL other than skip() /
c = Json_new();
if (!c) return 0; / memory fail */
value = parse_value(c, skip(value));
if (!value) {
Json_dispose(c);
return 0;
} /* parse failure. ep is set. */
return c;
}
More specifically, when it hits 'parse_value(c, skip(value));' and dives into the parse_value function which eventually returns 0:
/* Parser core - when encountering text, process appropriately. /
static const char parse_value (Json item, const char value) {
/* Referenced by Json_create(), parse_array(), and parse_object(). /
/ Always called with the result of skip(). /
#if SPINE_JSON_DEBUG / Checked at entry to graph, Json_create, and after every parse_ call. /
if (!value) return 0; / Fail on null. */
#endif
switch (*value) {
case 'n': {
if (!strncmp(value + 1, "ull", 3)) {
item->type = Json_NULL;
return value + 4;
}
break;
}
case 'f': {
if (!strncmp(value + 1, "alse", 4)) {
item->type = Json_False;
/* calloc prevents us needing item->type = Json_False or valueInt = 0 here */
return value + 5;
}
break;
}
case 't': {
if (!strncmp(value + 1, "rue", 3)) {
item->type = Json_True;
item->valueInt = 1;
return value + 4;
}
break;
}
case '\"':
return parse_string(item, value);
case '[':
return parse_array(item, value);
case '{':
return parse_object(item, value);
case '-': /* fallthrough */
case '0': /* fallthrough */
case '1': /* fallthrough */
case '2': /* fallthrough */
case '3': /* fallthrough */
case '4': /* fallthrough */
case '5': /* fallthrough */
case '6': /* fallthrough */
case '7': /* fallthrough */
case '8': /* fallthrough */
case '9':
return parse_number(item, value);
default:
break;
}
ep = value;
return 0; /* failure. */
}
So none of the switch cases are hit. When inspecting the const char* 'value' variable, its says it's holding the 'spineboy-ess.json' file name within it, so it's not like that variable is null or anything.
I recently changed parse_number
, so that may be what is causing this. However, as I said, I can not reproduce this with the 3.6 and 3.7-beta branch using any of the Spine projects (including the JSON you provided). Any way for me to reproduce this, e.g. could you send your test project?
Well, I discovered the issue. on this line:
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonData(json, "spineboy-ess.json");
I'm calling 'spSkeletonJson_readSkeletonData()' instead of 'spSkeletonJson_readSkeletonDataFile()'. I was only worried about calling the spSkeletonJson and not spSkeletonBinary, but didn't realize there were two very similar functions with spSkeletonJson.
Ahh, that's a sneaky gotcha!
Oh boy, sorry I didn't notice!
Yep, sure was sneaky.