json2apex
json2apex copied to clipboard
If a field has an explicitly null value in the JSON it is deserialized to Object.class even if later in the JSON that same field is represented as a specific type.
The following JSON:
{"example": [{"foo": null}, {"foo": "bar"}]}
Will generate the following APEX:
if (text == 'foo') { foo = parser.readValueAs(Object.class); }
And when executed will incur the following error:
System.JSONException: Apex Type unsupported in JSON: Object
I will be attempting to fix this on my own and will report back with a patch and a PR if you'd like. Thanks for the great tool. All the best.
-J
Just adding a quick note that this scenario also triggers the same issue:
{"outter":[{"foo":{"bar": null}}, {"foo":{"bar":"test"}},{"foo":{"bar":null}}]}
I implemented a fix for the original case (in my first post) by modifying the merge fields method so that it would merge even if the type wasn't null,
void mergeFields(ApexClass other) {
for (ApexMember key : other.getMembers().keySet() ) {
if (members.get(key) == null || members.get(key) == ApexPrimitive.OBJECT) {
members.put(key, other.getMembers().get(key));
}
}
}
so long as it was an Object. The supposition being that it had ran into a null and became object, but now it has run into a concrete type (like a string) and so it would prefer the non-Object designation.
But that didn't correct the whole issue, I don't know why. I'm imagining I just don't fully understand the merge logic so I'll need to dig deeper.
I'm tempted, for my purposes, to just ignore nulls when encountered and not to map them to a type at all. Leaving the office now so I'll update one final time tomorrow if I end up going that route. It might be worth having it as an option selection before parsing. It will probably be a lot quicker for me to implement than spending a ton of time which I unfortunately do not have understanding the merge logic.
-J
Additional case that breaks:
{
"foo": [
{
"bar": [{"baz":null}]
},
{
"bar": [{"baz":[{"bat": null}]}]
},
{
"bar": [{"baz":[{"bat": "hello"}]}]
}
]
}
I have fixed the scenarios listed in previous comments above already. As you might be able to tell by the timestamp this has been literally keeping me up. :-)
https://github.com/josephbleau/json2apex/commit/2f95c8b025889f7be0b5b4c0e9bd89be94b6c08f
Will make the PR once I cover this last scenario.
-J
Found one final additional scenario where, due to my change before, if the order so happens that we encounter a member of a type that is an ApexClass, but later encounter the same type (by member names), but one of those members has a value of null (and so becomes ApexPrimitive.OBJECT), we were not moving the details of the initially encountered type into the secondary object. Effectively, we are only ever merging one way and so we're losing some information. I worked around this by forcing lists to merge types both ways.
Apologies in advanced, as I've read the above paragraph a few times and I know that it is probably nonsense or hard to interpret exactly what I meant.
However, I've gotten to the point where I'm pretty sure it's working, in-so-much as it's now handling scenarios with null values in JSON, but the code probably should be refactored.
Additionally, I removed the class removal logic for now. I think I have a bug where I'm removing types even if they were needed because of my changes to the merge fields method. I'll probably look into this later, but for now I'm just going to make this PR although I don't fully encourage pulling it.
I will run the full suite of integration tests and post results with the PR.
I don't know how much this code-base is maintained at this point, but I'd be happy to have a Skype call or IRC chat to discuss the changes and get your perspective!
Thanks again for the awesome tool!
-J