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
Replace 'org.json:json' lib with 'com.google.code.gson' lib #1437
Replace 'org.json:json' lib with 'com.google.code.gson' lib #1437
Conversation
Attached the Sarif log generated with this change (using com.google.code.gson) @KengoTODA pls review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your contribution! Please check my comments for maintainability.
Also, please put https://github.com/google/gson/blob/gson-parent-2.8.6/LICENSE into spotbugs/licenses
directory to distribute.
extensionJson.addProperty("informationUri", informationUri.toString()); | ||
} | ||
if (organization != null) { | ||
extensionJson.addProperty("organization", String.valueOf(organization)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is are any reason to prefer String.valueOf( ... )
over organization.toString()
? If so, I want to make the intention clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
organization was declared as Object it should be String
public String toJSONString() { | ||
return String.format("\"%s\"", name().toLowerCase()); | ||
public String toJsonString() { | ||
return name().toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this method? The old one was provided to configure the org.json's serializer.
So I assume what we need is not this method but similar way to configure the serialier, like SerializedName.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added SerializedName annotation to the enum. Its useful if we use Gson toJson/fromJson methods to serialize/deserialize objects.
Current we create/setup JsonObject instead serializing object. e.g.
JsonObject result = new JsonObject();
result.addProperty("ruleId", ruleId);
result.addProperty("ruleIndex", ruleIndex);;
result.addProperty("level", level.toJsonString());
I think after POJO classes are introduced we should be able to use object serialization/deserialization and not need this method anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also tried
return new Gson().toJson(this);
but it returned string with double quotes "\"warning"\"
, but we need string without double quotes "warning"
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"); | ||
processRuns(jsonWriter); | ||
jsonWriter.endObject(); | ||
getBugCollection().bugsPopulated(); | ||
} catch (IOException e) { | ||
e.printStackTrace(System.err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume it's better to throw UncheckedIOException instead?
At least, we cannot ignore this exception like this, because we surely have problem in generated SARIF report file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we do not need to invoke e.printStackTrace(System.err);
. Who catches the error will print it.
And when we need to log, we use SLF4J as a logging facade so please do not use System.err
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed printStackTrace to let caller to log the error.
try { | ||
Gson gson = new Gson(); | ||
jsonWriter.name("runs").beginArray().beginObject(); | ||
BugCollectionAnalyser analyser = new BugCollectionAnalyser(getBugCollection()); | ||
processTool(jsonWriter, analyser.getRules()); | ||
processInvocations(jsonWriter, analyser.getBaseToId()); | ||
|
||
jsonWriter.name("results").beginArray(); | ||
analyser.getResults().forEach((result) -> gson.toJson(result, jsonWriter)); | ||
jsonWriter.endArray(); | ||
|
||
jsonWriter.name("originalUriBaseIds"); | ||
gson.toJson(analyser.getOriginalUriBaseIds(), jsonWriter); | ||
|
||
jsonWriter.endObject().endArray(); // end "runs", end "runs" array | ||
} catch (IOException e) { | ||
throw e; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This try-block seems needless.
try { | |
Gson gson = new Gson(); | |
jsonWriter.name("runs").beginArray().beginObject(); | |
BugCollectionAnalyser analyser = new BugCollectionAnalyser(getBugCollection()); | |
processTool(jsonWriter, analyser.getRules()); | |
processInvocations(jsonWriter, analyser.getBaseToId()); | |
jsonWriter.name("results").beginArray(); | |
analyser.getResults().forEach((result) -> gson.toJson(result, jsonWriter)); | |
jsonWriter.endArray(); | |
jsonWriter.name("originalUriBaseIds"); | |
gson.toJson(analyser.getOriginalUriBaseIds(), jsonWriter); | |
jsonWriter.endObject().endArray(); // end "runs", end "runs" array | |
} catch (IOException e) { | |
throw e; | |
} | |
Gson gson = new Gson(); | |
jsonWriter.name("runs").beginArray().beginObject(); | |
BugCollectionAnalyser analyser = new BugCollectionAnalyser(getBugCollection()); | |
processTool(jsonWriter, analyser.getRules()); | |
processInvocations(jsonWriter, analyser.getBaseToId()); | |
jsonWriter.name("results").beginArray(); | |
analyser.getResults().forEach((result) -> gson.toJson(result, jsonWriter)); | |
jsonWriter.endArray(); | |
jsonWriter.name("originalUriBaseIds"); | |
gson.toJson(analyser.getOriginalUriBaseIds(), jsonWriter); | |
jsonWriter.endObject().endArray(); // end "runs", end "runs" array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: fixed.
Most methods of Gson JsonWriter like name/value/begin.../end... throw IOException. That's why I have to catch it in try catch block.
try { | ||
Gson gson = new Gson(); | ||
jsonWriter.name("invocations").beginArray(); | ||
gson.toJson(invocation.toJsonObject(), jsonWriter); | ||
jsonWriter.endArray(); | ||
} catch (IOException e) { | ||
throw e; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This try-block seems needless.
try { | |
Gson gson = new Gson(); | |
jsonWriter.name("invocations").beginArray(); | |
gson.toJson(invocation.toJsonObject(), jsonWriter); | |
jsonWriter.endArray(); | |
} catch (IOException e) { | |
throw e; | |
} | |
Gson gson = new Gson(); | |
jsonWriter.name("invocations").beginArray(); | |
gson.toJson(invocation.toJsonObject(), jsonWriter); | |
jsonWriter.endArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
jsonWriter.key("rules").value(rules); | ||
jsonWriter.endObject().endObject(); | ||
private void processTool(@NonNull JsonWriter jsonWriter, @NonNull JsonArray rules) throws IOException { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This try-block is also needless. Simply throw IOException
to the caller side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
jsonWriter.endObject().endObject(); | ||
private void processTool(@NonNull JsonWriter jsonWriter, @NonNull JsonArray rules) throws IOException { | ||
try { | ||
Gson gson = new Gson(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it OK to generate Gson
instance on demand? Not sure its cost, but if it takes much resources (CPU or Java heap), consider to create it once and reuse by providing it via method parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a Gson member instead creating new instance for each place.
According to Gson user guide:
The Gson instance does not maintain any state while invoking Json operations. So, you are free to reuse the same object for multiple Json serialization and deserialization operations.
rules.forEach((rule) -> gson.toJson(rule, jsonWriter)); | ||
jsonWriter.endArray(); | ||
|
||
jsonWriter.endObject().endObject(); // end "driver", end "tool" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good comment to keep the code readable! 👍
DetectorFactoryCollection.instance().plugins().stream().map(Extension::fromPlugin).map(Extension::toJSONObject).forEach(jsonWriter::value); | ||
jsonWriter.endArray(); | ||
private void processExtensions(@NonNull JsonWriter jsonWriter) throws IOException { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this try-block seems needless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Just one change is necessary, please check.
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"); | ||
processRuns(jsonWriter); | ||
jsonWriter.endObject(); | ||
getBugCollection().bugsPopulated(); | ||
} catch (IOException e) { | ||
e.printStackTrace(System.err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we do not need to invoke e.printStackTrace(System.err);
. Who catches the error will print it.
And when we need to log, we use SLF4J as a logging facade so please do not use System.err
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for your contribution!
@spotbugs/everyone if possible, please double-check this PR. I'm recently little bit careless to make a high quality review. 🙇♂️ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for your contribution!
Thank you for reviewing!
try { | ||
Gson gson = new Gson(); | ||
jsonWriter.name("runs").beginArray().beginObject(); | ||
BugCollectionAnalyser analyser = new BugCollectionAnalyser(getBugCollection()); | ||
processTool(jsonWriter, analyser.getRules()); | ||
processInvocations(jsonWriter, analyser.getBaseToId()); | ||
|
||
jsonWriter.name("results").beginArray(); | ||
analyser.getResults().forEach((result) -> gson.toJson(result, jsonWriter)); | ||
jsonWriter.endArray(); | ||
|
||
jsonWriter.name("originalUriBaseIds"); | ||
gson.toJson(analyser.getOriginalUriBaseIds(), jsonWriter); | ||
|
||
jsonWriter.endObject().endArray(); // end "runs", end "runs" array | ||
} catch (IOException e) { | ||
throw e; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: fixed.
Most methods of Gson JsonWriter like name/value/begin.../end... throw IOException. That's why I have to catch it in try catch block.
extensionJson.addProperty("informationUri", informationUri.toString()); | ||
} | ||
if (organization != null) { | ||
extensionJson.addProperty("organization", String.valueOf(organization)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
organization was declared as Object it should be String
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"); | ||
processRuns(jsonWriter); | ||
jsonWriter.endObject(); | ||
getBugCollection().bugsPopulated(); | ||
} catch (IOException e) { | ||
e.printStackTrace(System.err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
jsonWriter.endObject().endObject(); | ||
private void processTool(@NonNull JsonWriter jsonWriter, @NonNull JsonArray rules) throws IOException { | ||
try { | ||
Gson gson = new Gson(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a Gson member instead creating new instance for each place.
According to Gson user guide:
The Gson instance does not maintain any state while invoking Json operations. So, you are free to reuse the same object for multiple Json serialization and deserialization operations.
public String toJSONString() { | ||
return String.format("\"%s\"", name().toLowerCase()); | ||
public String toJsonString() { | ||
return name().toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added SerializedName annotation to the enum. Its useful if we use Gson toJson/fromJson methods to serialize/deserialize objects.
Current we create/setup JsonObject instead serializing object. e.g.
JsonObject result = new JsonObject();
result.addProperty("ruleId", ruleId);
result.addProperty("ruleIndex", ruleIndex);;
result.addProperty("level", level.toJsonString());
I think after POJO classes are introduced we should be able to use object serialization/deserialization and not need this method anymore
public String toJSONString() { | ||
return String.format("\"%s\"", name().toLowerCase()); | ||
public String toJsonString() { | ||
return name().toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also tried
return new Gson().toJson(this);
but it returned string with double quotes "\"warning"\"
, but we need string without double quotes "warning"
try { | ||
Gson gson = new Gson(); | ||
jsonWriter.name("invocations").beginArray(); | ||
gson.toJson(invocation.toJsonObject(), jsonWriter); | ||
jsonWriter.endArray(); | ||
} catch (IOException e) { | ||
throw e; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
jsonWriter.key("rules").value(rules); | ||
jsonWriter.endObject().endObject(); | ||
private void processTool(@NonNull JsonWriter jsonWriter, @NonNull JsonArray rules) throws IOException { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
DetectorFactoryCollection.instance().plugins().stream().map(Extension::fromPlugin).map(Extension::toJSONObject).forEach(jsonWriter::value); | ||
jsonWriter.endArray(); | ||
private void processExtensions(@NonNull JsonWriter jsonWriter) throws IOException { | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"); | ||
processRuns(jsonWriter); | ||
jsonWriter.endObject(); | ||
getBugCollection().bugsPopulated(); | ||
} catch (IOException e) { | ||
e.printStackTrace(System.err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed printStackTrace to let caller to log the error.
Attached the Sarif log generated by SpotBugs with the Gson changes. |
@KengoTODA Thanks! |
Fantastic! |
This is for issue #1279