• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

torand / jsonschema2java / 22553968753

01 Mar 2026 10:11PM UTC coverage: 83.689% (+1.3%) from 82.424%
22553968753

push

github

torand
feat: add config parameter 'durationClassName' to specify a custom class to represent string schemas with format "duration" in generated code

328 of 433 branches covered (75.75%)

Branch coverage included in aggregate %.

16 of 16 new or added lines in 5 files covered. (100.0%)

41 existing lines in 6 files now uncovered.

888 of 1020 relevant lines covered (87.06%)

5.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.48
/src/main/java/io/github/torand/jsonschema2java/writers/java/JavaPojoWriter.java
1
/*
2
 * Copyright (c) 2024-2026 Tore Eide Andersen
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package io.github.torand.jsonschema2java.writers.java;
17

18
import io.github.torand.jsonschema2java.generators.Options;
19
import io.github.torand.jsonschema2java.model.AnnotatedTypeName;
20
import io.github.torand.jsonschema2java.model.PojoInfo;
21
import io.github.torand.jsonschema2java.model.PropertyInfo;
22
import io.github.torand.jsonschema2java.utils.PackageUtils;
23
import io.github.torand.jsonschema2java.writers.BaseWriter;
24
import io.github.torand.jsonschema2java.writers.PojoWriter;
25

26
import java.io.Writer;
27
import java.util.List;
28
import java.util.concurrent.atomic.AtomicInteger;
29
import java.util.function.Predicate;
30

31
import static io.github.torand.javacommons.collection.CollectionHelper.nonEmpty;
32
import static io.github.torand.jsonschema2java.utils.PackageUtils.isFqnInPackage;
33
import static java.util.function.Predicate.not;
34
import static java.util.stream.Collectors.joining;
35

36
/**
37
 * Writes Java code for a pojo.
38
 */
39
public class JavaPojoWriter extends BaseWriter implements PojoWriter {
40

41
    public JavaPojoWriter(Writer writer, Options opts) {
42
        super(writer, opts);
4✔
43
    }
1✔
44

45
    @Override
46
    public void write(PojoInfo pojoInfo) {
47
        writeLine("package %s;", opts.getModelPackage(pojoInfo.modelSubpackage()));
13✔
48
        writeNewLine();
2✔
49

50
        writeNonJavaImports(pojoInfo);
3✔
51
        writeJavaImports(pojoInfo);
3✔
52

53
        if (pojoInfo.isDeprecated()) {
3!
UNCOV
54
            writeLine("/// @deprecated %s".formatted(pojoInfo.deprecationMessage()));
×
UNCOV
55
            writeLine("@Deprecated");
×
56
        }
57

58
        pojoInfo.annotations().forEach(a -> writeLine(a.annotation()));
12✔
59

60
        if (opts.pojosAsRecords()) {
4✔
61
            writeLine("public record %s (".formatted(pojoInfo.name()));
14✔
62
        } else {
63
            writeLine("public class %s {".formatted(pojoInfo.name()));
13✔
64
        }
65

66
        AtomicInteger propNo = new AtomicInteger(1);
5✔
67
        pojoInfo.properties().forEach(propInfo -> {
7✔
68
            writeNewLine();
2✔
69
            writePropertyAnnotationLines(propInfo);
3✔
70
            writePropertyTypeAndNameLines(propInfo);
3✔
71

72
            if (opts.pojosAsRecords()) {
4!
73
                if (propNo.getAndIncrement() < pojoInfo.properties().size()) {
6✔
74
                    writeLine(",");
6✔
75
                } else {
76
                    writeNewLine();
3✔
77
                }
78
            } else {
UNCOV
79
                writeLine(";");
×
80
            }
81
        });
1✔
82

83
        if (opts.pojosAsRecords()) {
4✔
84
            writeLine(") {");
5✔
85
            writeNewLine();
2✔
86
            writeLine("}");
6✔
87
        } else {
88
            writeNewLine();
2✔
89
            writeNoArgConstructor(pojoInfo.name());
4✔
90
            if (nonEmpty(pojoInfo.properties())) {
4!
UNCOV
91
                writeNewLine();
×
UNCOV
92
                writeParameterizedConstructor(pojoInfo.name(), pojoInfo.properties());
×
93
            }
94
            writeLine("}");
5✔
95
        }
96
    }
1✔
97

98
    private void writeJavaImports(PojoInfo pojoInfo) {
99
        List<String> imports = pojoInfo.aggregatedNormalImports().stream()
4✔
100
            .filter(PackageUtils::isJavaPackage)
2✔
101
            .filter(not(PackageUtils::isFundamentalJavaClass))
4✔
102
            .map("import %s;"::formatted)
10✔
103
            .toList();
2✔
104

105
        if (nonEmpty(imports)) {
3✔
106
            imports.forEach(this::writeLine);
10✔
107
            writeNewLine();
2✔
108
        }
109
    }
1✔
110

111
    private void writeNonJavaImports(PojoInfo pojoInfo) {
112
        Predicate<String> isInSamePackage = fqn -> isFqnInPackage(fqn, opts.getModelPackage(pojoInfo.modelSubpackage()));
12✔
113

114
        List<String> imports = pojoInfo.aggregatedNormalImports().stream()
4✔
115
            .filter(not(PackageUtils::isJavaPackage))
3✔
116
            .filter(not(isInSamePackage))
4✔
117
            .map("import %s;"::formatted)
10✔
118
            .toList();
2✔
119

120
        if (nonEmpty(imports)) {
3!
121
            imports.forEach(this::writeLine);
10✔
122
            writeNewLine();
2✔
123
        }
124
    }
1✔
125

126
    private void writeNoArgConstructor(String name) {
127
        writeIndent(1);
3✔
128
        writeLine("public %s() {", name);
9✔
129
        writeIndent(1);
3✔
130
        writeLine("}");
5✔
131
    }
1✔
132

133
    private void writeParameterizedConstructor(String name, List<PropertyInfo> props) {
134
        writeIndent(1);
×
135
        writeLine("public %s(%s) {", name, props.stream().map(p -> p.type().getFullName() + " " + p.name()).collect(joining(", ")));
×
UNCOV
136
        props.forEach(p -> {
×
UNCOV
137
            writeIndent(2);
×
UNCOV
138
            writeLine("this.%s = %s;", p.name(), p.name());
×
UNCOV
139
        });
×
UNCOV
140
        writeIndent(1);
×
UNCOV
141
        writeLine("}");
×
UNCOV
142
    }
×
143

144
    private void writePropertyAnnotationLines(PropertyInfo propInfo) {
145
        if (propInfo.isDeprecated()) {
3✔
146
            writeIndent(1);
3✔
147
            writeLine("/// @deprecated %s".formatted(propInfo.deprecationMessage()));
13✔
148
            writeIndent(1);
3✔
149
            writeLine("@Deprecated");
5✔
150
        }
151
        propInfo.annotations().forEach(a -> {
5✔
152
            writeIndent(1);
3✔
153
            writeLine(a.annotation());
6✔
154
        });
1✔
155
    }
1✔
156

157
    private void writePropertyTypeAndNameLines(PropertyInfo propInfo) {
158
        AnnotatedTypeName annotatedTypeName = propInfo.type().getAnnotatedFullName();
4✔
159

160
        annotatedTypeName.annotations().forEach(a -> {
5✔
161
            writeIndent(1);
3✔
162
            writeLine(a);
5✔
163
        });
1✔
164

165
        writeIndent(1);
3✔
166
        if (opts.pojosAsRecords()) {
4!
167
            write("%s %s".formatted(annotatedTypeName.typeName(), propInfo.name()));
19✔
168
        } else {
UNCOV
169
            write("public %s %s".formatted(annotatedTypeName.typeName(), propInfo.name()));
×
170
        }
171
    }
1✔
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc