Skip to content

Commit

Permalink
Add json formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
charphi committed Apr 3, 2024
1 parent cb785c2 commit 3458ffe
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Add check on GitHub commit SHAs [#223](https://github.com/nbbrd/heylogs/issues/223)
- Improve list command output [#231](https://github.com/nbbrd/heylogs/issues/231)
- Add error severity to failures [#17](https://github.com/nbbrd/heylogs/issues/17)
- Add json formatting [#118](https://github.com/nbbrd/heylogs/issues/118)

### Changed

Expand Down
5 changes: 5 additions & 0 deletions heylogs-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@
<groupId>com.github.nbbrd.java-io-util</groupId>
<artifactId>java-io-http</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>

<!-- test only -->
<dependency>
Expand Down
130 changes: 130 additions & 0 deletions heylogs-api/src/main/java/internal/heylogs/JsonFormat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package internal.heylogs;

import com.google.gson.*;
import lombok.NonNull;
import nbbrd.design.MightBeGenerated;
import nbbrd.heylogs.Problem;
import nbbrd.heylogs.Resource;
import nbbrd.heylogs.Status;
import nbbrd.heylogs.TimeRange;
import nbbrd.heylogs.spi.Format;
import nbbrd.heylogs.spi.FormatType;
import nbbrd.heylogs.spi.RuleIssue;
import nbbrd.heylogs.spi.RuleSeverity;
import nbbrd.service.ServiceProvider;

import java.io.IOException;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

@ServiceProvider
public final class JsonFormat implements Format {

public static final String ID = "json";

@Override
public @NonNull String getFormatId() {
return ID;
}

@Override
public @NonNull String getFormatName() {
return "Outputs JSON-serialized results.";
}

@Override
public @NonNull Set<FormatType> getSupportedFormatTypes() {
return EnumSet.allOf(FormatType.class);
}

@Override
public void formatProblems(@NonNull Appendable appendable, @NonNull String source, @NonNull List<Problem> problems) throws IOException {
try {
GSON.toJson(new FileProblems(source, problems), appendable);
} catch (JsonIOException ex) {
throw new IOException(ex);
}
}

@Override
public void formatStatus(@NonNull Appendable appendable, @NonNull String source, @NonNull Status status) throws IOException {
try {
GSON.toJson(new FileStatus(source, status), appendable);
} catch (JsonIOException ex) {
throw new IOException(ex);
}
}

@Override
public void formatResources(@NonNull Appendable appendable, @NonNull List<Resource> resources) throws IOException {
try {
GSON.toJson(resources, appendable);
} catch (JsonIOException ex) {
throw new IOException(ex);
}
}

@lombok.Value
private static class FileProblems {
String filePath;
List<Problem> messages;
}

@lombok.Value
private static class FileStatus {
String filePath;
Status status;
}

private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(Problem.class, (JsonSerializer<Problem>) JsonFormat::serializeProblem)
.registerTypeAdapter(Problem.class, (JsonDeserializer<Problem>) JsonFormat::deserializeProblem)
.registerTypeAdapter(TimeRange.class, (JsonSerializer<TimeRange>) JsonFormat::serializeTimeRange)
.registerTypeAdapter(TimeRange.class, (JsonDeserializer<TimeRange>) JsonFormat::deserializeTimeRange)
.setPrettyPrinting()
.create();

@MightBeGenerated
private static JsonElement serializeProblem(Problem src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("ruleId", src.getId());
result.addProperty("severity", src.getSeverity().toCode());
result.addProperty("message", src.getIssue().getMessage());
result.addProperty("line", src.getIssue().getLine());
result.addProperty("column", src.getIssue().getColumn());
return result;
}

@MightBeGenerated
private static Problem deserializeProblem(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
JsonObject x = json.getAsJsonObject();
return Problem
.builder()
.id(x.get("ruleId").getAsString())
.severity(RuleSeverity.parseCode(x.get("severity").getAsInt()))
.issue(RuleIssue
.builder()
.message(x.get("message").getAsString())
.line(x.get("line").getAsInt())
.column(x.get("column").getAsInt())
.build())
.build();
}

@MightBeGenerated
private static JsonElement serializeTimeRange(TimeRange src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("from", src.getFrom().toString());
result.addProperty("to", src.getTo().toString());
return result;
}

@MightBeGenerated
private static TimeRange deserializeTimeRange(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
JsonObject x = json.getAsJsonObject();
return TimeRange.of(LocalDate.parse(x.get("from").getAsString()), LocalDate.parse(x.get("to").getAsString()));
}
}
21 changes: 20 additions & 1 deletion heylogs-api/src/main/java/nbbrd/heylogs/spi/RuleSeverity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package nbbrd.heylogs.spi;

import lombok.NonNull;
import nbbrd.design.RepresentableAsInt;
import nbbrd.design.RepresentableAsString;
import nbbrd.design.StaticFactoryMethod;

import java.util.stream.Stream;

//@RepresentableAsString
@RepresentableAsInt(formatMethodName = "toCode", parseMethodName = "parseCode")
@lombok.AllArgsConstructor
public enum RuleSeverity {

Expand All @@ -18,6 +27,16 @@ public enum RuleSeverity {
*/
ERROR(2);

@lombok.Getter
private final int code;

public int toCode() {
return code;
}

@StaticFactoryMethod
public static @NonNull RuleSeverity parseCode(int code) {
return Stream.of(values()).filter(value -> value.code == code)
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
5 changes: 3 additions & 2 deletions heylogs-api/src/test/java/nbbrd/heylogs/HeylogsTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nbbrd.heylogs;

import internal.heylogs.SemverRule;
import internal.heylogs.StylishFormat;
import nbbrd.heylogs.spi.Rule;
import nbbrd.heylogs.spi.RuleIssue;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -56,7 +57,7 @@ public void testFormatProblems() throws IOException {
.isThrownBy(() -> Heylogs.ofServiceLoader().formatProblems("other", new StringBuilder(), "", emptyList()));

StringBuilder output = new StringBuilder();
Heylogs.ofServiceLoader().formatProblems(FIRST_FORMAT_AVAILABLE, output, "file1", asList(Problem.builder().id("rule1").severity(ERROR).issue(RuleIssue.builder().message("some message").line(10).column(20).build()).build()));
Heylogs.ofServiceLoader().formatProblems(StylishFormat.ID, output, "file1", asList(Problem.builder().id("rule1").severity(ERROR).issue(RuleIssue.builder().message("some message").line(10).column(20).build()).build()));
assertThat(output.toString())
.isEqualToIgnoringNewLines(
"file1\n" +
Expand Down Expand Up @@ -112,7 +113,7 @@ public void testFormatStatus() throws IOException {
.isThrownBy(() -> Heylogs.ofServiceLoader().formatStatus("other", new StringBuilder(), "", Status.builder().build()));

StringBuilder output = new StringBuilder();
Heylogs.ofServiceLoader().formatStatus(FIRST_FORMAT_AVAILABLE, output, "file1", new Status(
Heylogs.ofServiceLoader().formatStatus(StylishFormat.ID, output, "file1", new Status(
1,
TimeRange.of(LocalDate.of(2019, 2, 15), LocalDate.of(2019, 2, 15)),
true, " ()",
Expand Down

0 comments on commit 3458ffe

Please sign in to comment.