avrotize 2.18.2__tar.gz → 2.20.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. {avrotize-2.18.2 → avrotize-2.20.0}/PKG-INFO +29 -2
  2. {avrotize-2.18.2 → avrotize-2.20.0}/README.md +26 -1
  3. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/_version.py +3 -3
  4. avrotize-2.20.0/avrotize/avrotocsharp/project.csproj.jinja +24 -0
  5. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp/testproject.csproj.jinja +3 -3
  6. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp.py +21 -2
  7. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojava/testproject.pom.jinja +4 -3
  8. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojava.py +16 -6
  9. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/class_core.ts.jinja +12 -0
  10. avrotize-2.20.0/avrotize/avrotots/class_test.ts.jinja +77 -0
  11. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots.py +96 -0
  12. avrotize-2.20.0/avrotize/cddltostructure.py +1841 -0
  13. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/commands.json +226 -0
  14. avrotize-2.20.0/avrotize/constants.py +72 -0
  15. avrotize-2.20.0/avrotize/dependencies/cpp/vcpkg/vcpkg.json +19 -0
  16. avrotize-2.18.2/avrotize/avrotocsharp/project.csproj.jinja → avrotize-2.20.0/avrotize/dependencies/cs/net90/dependencies.csproj +15 -12
  17. avrotize-2.20.0/avrotize/dependencies/go/go121/go.mod +6 -0
  18. avrotize-2.20.0/avrotize/dependencies/java/jdk21/pom.xml +91 -0
  19. avrotize-2.20.0/avrotize/dependencies/python/py312/requirements.txt +13 -0
  20. avrotize-2.20.0/avrotize/dependencies/rust/stable/Cargo.toml +17 -0
  21. avrotize-2.20.0/avrotize/dependencies/typescript/node22/package.json +16 -0
  22. avrotize-2.20.0/avrotize/dependency_version.py +432 -0
  23. avrotize-2.20.0/avrotize/structuretocddl.py +597 -0
  24. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/dataclass_core.jinja +6 -1
  25. avrotize-2.20.0/avrotize/structuretocsharp/json_structure_converters.cs.jinja +399 -0
  26. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/program.cs.jinja +11 -6
  27. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/project.csproj.jinja +4 -3
  28. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/testproject.csproj.jinja +4 -3
  29. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp.py +311 -21
  30. avrotize-2.20.0/avrotize/structuretojava/choice_core.jinja +34 -0
  31. avrotize-2.20.0/avrotize/structuretojava/class_core.jinja +23 -0
  32. avrotize-2.20.0/avrotize/structuretojava/enum_core.jinja +18 -0
  33. avrotize-2.20.0/avrotize/structuretojava/equals_hashcode.jinja +30 -0
  34. avrotize-2.20.0/avrotize/structuretojava/pom.xml.jinja +26 -0
  35. avrotize-2.20.0/avrotize/structuretojava/tuple_core.jinja +49 -0
  36. avrotize-2.20.0/avrotize/structuretojava.py +853 -0
  37. {avrotize-2.18.2 → avrotize-2.20.0}/pyproject.toml +4 -2
  38. avrotize-2.18.2/avrotize/constants.py +0 -5
  39. {avrotize-2.18.2 → avrotize-2.20.0}/LICENSE +0 -0
  40. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/__init__.py +0 -0
  41. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/__main__.py +0 -0
  42. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/asn1toavro.py +0 -0
  43. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotize.py +0 -0
  44. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp/CMakeLists.txt.jinja +0 -0
  45. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp/build.bat.jinja +0 -0
  46. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp/build.sh.jinja +0 -0
  47. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp/dataclass_body.jinja +0 -0
  48. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp/vcpkg.json.jinja +0 -0
  49. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocpp.py +0 -0
  50. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp/class_test.cs.jinja +0 -0
  51. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp/dataclass_core.jinja +0 -0
  52. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp/enum_test.cs.jinja +0 -0
  53. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsharp/project.sln.jinja +0 -0
  54. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotocsv.py +0 -0
  55. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotodatapackage.py +0 -0
  56. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotodb.py +0 -0
  57. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo/go_enum.jinja +0 -0
  58. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo/go_helpers.jinja +0 -0
  59. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo/go_struct.jinja +0 -0
  60. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo/go_test.jinja +0 -0
  61. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo/go_union.jinja +0 -0
  62. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotogo.py +0 -0
  63. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotographql.py +0 -0
  64. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotoiceberg.py +0 -0
  65. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojava/class_test.java.jinja +0 -0
  66. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojava/enum_test.java.jinja +0 -0
  67. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojs.py +0 -0
  68. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojsons.py +0 -0
  69. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotojstruct.py +0 -0
  70. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotokusto.py +0 -0
  71. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotomd/README.md.jinja +0 -0
  72. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotomd.py +0 -0
  73. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotools.py +0 -0
  74. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotoparquet.py +0 -0
  75. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotoproto.py +0 -0
  76. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython/dataclass_core.jinja +0 -0
  77. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython/enum_core.jinja +0 -0
  78. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython/pyproject_toml.jinja +0 -0
  79. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython/test_class.jinja +0 -0
  80. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython/test_enum.jinja +0 -0
  81. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotopython.py +0 -0
  82. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotorust/dataclass_enum.rs.jinja +0 -0
  83. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotorust/dataclass_struct.rs.jinja +0 -0
  84. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotorust/dataclass_union.rs.jinja +0 -0
  85. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotorust.py +0 -0
  86. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/enum_core.ts.jinja +0 -0
  87. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/gitignore.jinja +0 -0
  88. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/index.ts.jinja +0 -0
  89. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/package.json.jinja +0 -0
  90. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotots/tsconfig.json.jinja +0 -0
  91. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/avrotoxsd.py +0 -0
  92. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/common.py +0 -0
  93. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/csvtoavro.py +0 -0
  94. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/datapackagetoavro.py +0 -0
  95. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/dependency_resolver.py +0 -0
  96. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/generic/generic.avsc +0 -0
  97. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/jsonstoavro.py +0 -0
  98. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/jsonstostructure.py +0 -0
  99. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/jstructtoavro.py +0 -0
  100. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/kstructtoavro.py +0 -0
  101. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/kustotoavro.py +0 -0
  102. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/parquettoavro.py +0 -0
  103. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/proto2parser.py +0 -0
  104. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/proto3parser.py +0 -0
  105. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototoavro.py +0 -0
  106. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/any.avsc +0 -0
  107. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/api.avsc +0 -0
  108. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/duration.avsc +0 -0
  109. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/field_mask.avsc +0 -0
  110. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/struct.avsc +0 -0
  111. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/timestamp.avsc +0 -0
  112. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/type.avsc +0 -0
  113. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/prototypes/wrappers.avsc +0 -0
  114. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp/CMakeLists.txt.jinja +0 -0
  115. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp/build.bat.jinja +0 -0
  116. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp/build.sh.jinja +0 -0
  117. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp/dataclass_body.jinja +0 -0
  118. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp/vcpkg.json.jinja +0 -0
  119. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocpp.py +0 -0
  120. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/class_test.cs.jinja +0 -0
  121. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/enum_test.cs.jinja +0 -0
  122. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/project.sln.jinja +0 -0
  123. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsharp/tuple_converter.cs.jinja +0 -0
  124. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretocsv.py +0 -0
  125. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretodatapackage.py +0 -0
  126. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretodb.py +0 -0
  127. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo/go_enum.jinja +0 -0
  128. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo/go_helpers.jinja +0 -0
  129. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo/go_interface.jinja +0 -0
  130. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo/go_struct.jinja +0 -0
  131. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo/go_test.jinja +0 -0
  132. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretogo.py +0 -0
  133. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretographql.py +0 -0
  134. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretoiceberg.py +0 -0
  135. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretojsons.py +0 -0
  136. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretokusto.py +0 -0
  137. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretomd/README.md.jinja +0 -0
  138. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretomd.py +0 -0
  139. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretoproto.py +0 -0
  140. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/dataclass_core.jinja +0 -0
  141. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/enum_core.jinja +0 -0
  142. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/map_alias.jinja +0 -0
  143. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/pyproject_toml.jinja +0 -0
  144. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/test_class.jinja +0 -0
  145. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython/test_enum.jinja +0 -0
  146. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretopython.py +0 -0
  147. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretorust/dataclass_enum.rs.jinja +0 -0
  148. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretorust/dataclass_struct.rs.jinja +0 -0
  149. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretorust/dataclass_union.rs.jinja +0 -0
  150. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretorust.py +0 -0
  151. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/class_core.ts.jinja +0 -0
  152. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/enum_core.ts.jinja +0 -0
  153. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/gitignore.jinja +0 -0
  154. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/index.ts.jinja +0 -0
  155. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/package.json.jinja +0 -0
  156. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/test_class.ts.jinja +0 -0
  157. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots/tsconfig.json.jinja +0 -0
  158. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretots.py +0 -0
  159. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/structuretoxsd.py +0 -0
  160. {avrotize-2.18.2 → avrotize-2.20.0}/avrotize/xsdtoavro.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avrotize
3
- Version: 2.18.2
3
+ Version: 2.20.0
4
4
  Summary: Tools to convert from and to Avro Schema from various other schema languages.
5
5
  Author-email: Clemens Vasters <clemensv@microsoft.com>
6
6
  Requires-Python: >=3.10
@@ -24,6 +24,8 @@ Requires-Dist: jinja2>=3.1.4
24
24
  Requires-Dist: pyiceberg>=0.10.0
25
25
  Requires-Dist: pandas>=2.2.2
26
26
  Requires-Dist: docker>=7.1.0
27
+ Requires-Dist: cddlparser>=0.5.0
28
+ Requires-Dist: json-structure>=0.1.8
27
29
  Requires-Dist: pytest>=8.3.2 ; extra == "dev"
28
30
  Requires-Dist: fastavro>=1.9.5 ; extra == "dev"
29
31
  Requires-Dist: xmlschema>=3.3.2 ; extra == "dev"
@@ -125,10 +127,11 @@ Generate code from JSON Structure:
125
127
 
126
128
  - [`avrotize s2cpp`](#convert-json-structure-to-c-classes) - Generate C++ code from JSON Structure schema.
127
129
  - [`avrotize s2cs`](#convert-json-structure-to-c-classes) - Generate C# code from JSON Structure schema.
130
+ - [`avrotize s2go`](#convert-json-structure-to-go-classes) - Generate Go code from JSON Structure schema.
131
+ - [`avrotize s2java`](#convert-json-structure-to-java-classes) - Generate Java code from JSON Structure schema.
128
132
  - [`avrotize s2py`](#convert-json-structure-to-python-classes) - Generate Python code from JSON Structure schema.
129
133
  - [`avrotize s2rust`](#convert-json-structure-to-rust-classes) - Generate Rust code from JSON Structure schema.
130
134
  - [`avrotize s2ts`](#convert-json-structure-to-typescript-classes) - Generate TypeScript code from JSON Structure schema.
131
- - [`avrotize s2go`](#convert-json-structure-to-go-classes) - Generate Go code from JSON Structure schema.
132
135
 
133
136
  Direct JSON Structure conversions:
134
137
 
@@ -1040,6 +1043,30 @@ Conversion notes:
1040
1043
  - The tool generates a complete Go module with go.mod file, struct definitions, helper functions, and unit tests.
1041
1044
  - Generated code includes methods for JSON serialization/deserialization when annotations are enabled.
1042
1045
 
1046
+ ### Convert JSON Structure to Java classes
1047
+
1048
+ ```bash
1049
+ avrotize s2java <path_to_structure_schema_file> [--out <path_to_java_dir>] [--package <java_package>] [--jackson-annotation] [--pascal-properties]
1050
+ ```
1051
+
1052
+ Parameters:
1053
+
1054
+ - `<path_to_structure_schema_file>`: The path to the JSON Structure schema file to be converted. If omitted, the file is read from stdin.
1055
+ - `--out`: The path to the directory to write the Java classes to. Required.
1056
+ - `--package`: (optional) The Java package name for the generated classes.
1057
+ - `--jackson-annotation`: (optional) Use Jackson annotations for JSON serialization (default: true).
1058
+ - `--pascal-properties`: (optional) Use PascalCase for property names.
1059
+
1060
+ Conversion notes:
1061
+
1062
+ - The tool generates Java classes from JSON Structure schemas. Each object type is converted to a Java class with getter/setter methods.
1063
+ - JSON Structure primitive types are mapped to Java types. Extended types like `date`, `time`, `datetime` are mapped to `LocalDate`, `LocalTime`, `Instant`.
1064
+ - Integer types (int8-int64, uint8-uint64) are mapped to corresponding Java types. `uint64` uses `BigInteger` for full range support.
1065
+ - Choice types (discriminated unions) use Jackson polymorphism with `@JsonTypeInfo` and `@JsonSubTypes` annotations.
1066
+ - Tuple types serialize as JSON arrays using `@JsonFormat(shape = Shape.ARRAY)`.
1067
+ - The tool generates a complete Maven project with pom.xml including Jackson dependencies.
1068
+ - Generated classes include `equals()` and `hashCode()` implementations.
1069
+
1043
1070
  ### Convert Avrotize Schema to Datapackage schema
1044
1071
 
1045
1072
  ```bash
@@ -79,10 +79,11 @@ Generate code from JSON Structure:
79
79
 
80
80
  - [`avrotize s2cpp`](#convert-json-structure-to-c-classes) - Generate C++ code from JSON Structure schema.
81
81
  - [`avrotize s2cs`](#convert-json-structure-to-c-classes) - Generate C# code from JSON Structure schema.
82
+ - [`avrotize s2go`](#convert-json-structure-to-go-classes) - Generate Go code from JSON Structure schema.
83
+ - [`avrotize s2java`](#convert-json-structure-to-java-classes) - Generate Java code from JSON Structure schema.
82
84
  - [`avrotize s2py`](#convert-json-structure-to-python-classes) - Generate Python code from JSON Structure schema.
83
85
  - [`avrotize s2rust`](#convert-json-structure-to-rust-classes) - Generate Rust code from JSON Structure schema.
84
86
  - [`avrotize s2ts`](#convert-json-structure-to-typescript-classes) - Generate TypeScript code from JSON Structure schema.
85
- - [`avrotize s2go`](#convert-json-structure-to-go-classes) - Generate Go code from JSON Structure schema.
86
87
 
87
88
  Direct JSON Structure conversions:
88
89
 
@@ -994,6 +995,30 @@ Conversion notes:
994
995
  - The tool generates a complete Go module with go.mod file, struct definitions, helper functions, and unit tests.
995
996
  - Generated code includes methods for JSON serialization/deserialization when annotations are enabled.
996
997
 
998
+ ### Convert JSON Structure to Java classes
999
+
1000
+ ```bash
1001
+ avrotize s2java <path_to_structure_schema_file> [--out <path_to_java_dir>] [--package <java_package>] [--jackson-annotation] [--pascal-properties]
1002
+ ```
1003
+
1004
+ Parameters:
1005
+
1006
+ - `<path_to_structure_schema_file>`: The path to the JSON Structure schema file to be converted. If omitted, the file is read from stdin.
1007
+ - `--out`: The path to the directory to write the Java classes to. Required.
1008
+ - `--package`: (optional) The Java package name for the generated classes.
1009
+ - `--jackson-annotation`: (optional) Use Jackson annotations for JSON serialization (default: true).
1010
+ - `--pascal-properties`: (optional) Use PascalCase for property names.
1011
+
1012
+ Conversion notes:
1013
+
1014
+ - The tool generates Java classes from JSON Structure schemas. Each object type is converted to a Java class with getter/setter methods.
1015
+ - JSON Structure primitive types are mapped to Java types. Extended types like `date`, `time`, `datetime` are mapped to `LocalDate`, `LocalTime`, `Instant`.
1016
+ - Integer types (int8-int64, uint8-uint64) are mapped to corresponding Java types. `uint64` uses `BigInteger` for full range support.
1017
+ - Choice types (discriminated unions) use Jackson polymorphism with `@JsonTypeInfo` and `@JsonSubTypes` annotations.
1018
+ - Tuple types serialize as JSON arrays using `@JsonFormat(shape = Shape.ARRAY)`.
1019
+ - The tool generates a complete Maven project with pom.xml including Jackson dependencies.
1020
+ - Generated classes include `equals()` and `hashCode()` implementations.
1021
+
997
1022
  ### Convert Avrotize Schema to Datapackage schema
998
1023
 
999
1024
  ```bash
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2.18.2'
32
- __version_tuple__ = version_tuple = (2, 18, 2)
31
+ __version__ = version = '2.20.0'
32
+ __version_tuple__ = version_tuple = (2, 20, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g857734aaf'
34
+ __commit_id__ = commit_id = 'gd4e6f7652'
@@ -0,0 +1,24 @@
1
+ <Project Sdk="Microsoft.NET.Sdk">
2
+ <PropertyGroup>
3
+ <TargetFramework>net9.0</TargetFramework>
4
+ <Nullable>enable</Nullable>
5
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ {%- if avro_annotation %}
9
+ <PackageReference Include="Apache.Avro" Version="{{ CSHARP_AVRO_VERSION }}" />
10
+ {%- endif %}
11
+ {%- if newtonsoft_json_annotation %}
12
+ <PackageReference Include="Newtonsoft.Json" Version="{{ NEWTONSOFT_JSON_VERSION }}" />
13
+ {%- endif %}
14
+ {%- if system_text_json_annotation %}
15
+ <PackageReference Include="System.Text.Json" Version="{{ SYSTEM_TEXT_JSON_VERSION }}" />
16
+ {%- endif %}
17
+ <PackageReference Include="System.Memory.Data" Version="{{ SYSTEM_MEMORY_DATA_VERSION }}" />
18
+ </ItemGroup>
19
+ <ItemGroup>
20
+ <PackageReference Include="NUnit" Version="{{ NUNIT_VERSION }}" />
21
+ <PackageReference Include="NUnit3TestAdapter" Version="{{ NUNIT_ADAPTER_VERSION }}" />
22
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="{{ MSTEST_SDK_VERSION }}" />
23
+ </ItemGroup>
24
+ </Project>
@@ -8,8 +8,8 @@
8
8
  <ProjectReference Include="../src/{{project_name | pascal}}.csproj"/>
9
9
  </ItemGroup>
10
10
  <ItemGroup>
11
- <PackageReference Include="NUnit" Version="4.3.2" />
12
- <PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
13
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
11
+ <PackageReference Include="NUnit" Version="{{ NUNIT_VERSION }}" />
12
+ <PackageReference Include="NUnit3TestAdapter" Version="{{ NUNIT_ADAPTER_VERSION }}" />
13
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="{{ MSTEST_SDK_VERSION }}" />
14
14
  </ItemGroup>
15
15
  </Project>
@@ -9,6 +9,15 @@ from typing import Any, Dict, List, Tuple, Union, cast
9
9
  import uuid
10
10
 
11
11
  from avrotize.common import build_flat_type_dict, inline_avro_references, is_generic_avro_type, pascal, process_template
12
+ from avrotize.constants import (
13
+ CSHARP_AVRO_VERSION,
14
+ NEWTONSOFT_JSON_VERSION,
15
+ SYSTEM_TEXT_JSON_VERSION,
16
+ SYSTEM_MEMORY_DATA_VERSION,
17
+ NUNIT_VERSION,
18
+ NUNIT_ADAPTER_VERSION,
19
+ MSTEST_SDK_VERSION,
20
+ )
12
21
  import glob
13
22
 
14
23
  JsonNode = Dict[str, 'JsonNode'] | List['JsonNode'] | str | None
@@ -957,7 +966,14 @@ class AvroToCSharp:
957
966
  avro_annotation=self.avro_annotation,
958
967
  system_xml_annotation=self.system_xml_annotation,
959
968
  system_text_json_annotation=self.system_text_json_annotation,
960
- newtonsoft_json_annotation=self.newtonsoft_json_annotation))
969
+ newtonsoft_json_annotation=self.newtonsoft_json_annotation,
970
+ CSHARP_AVRO_VERSION=CSHARP_AVRO_VERSION,
971
+ NEWTONSOFT_JSON_VERSION=NEWTONSOFT_JSON_VERSION,
972
+ SYSTEM_TEXT_JSON_VERSION=SYSTEM_TEXT_JSON_VERSION,
973
+ SYSTEM_MEMORY_DATA_VERSION=SYSTEM_MEMORY_DATA_VERSION,
974
+ NUNIT_VERSION=NUNIT_VERSION,
975
+ NUNIT_ADAPTER_VERSION=NUNIT_ADAPTER_VERSION,
976
+ MSTEST_SDK_VERSION=MSTEST_SDK_VERSION))
961
977
  if not glob.glob(os.path.join(output_dir, "test", "*.csproj")):
962
978
  csproj_test_file = os.path.join(
963
979
  output_dir, "test", f"{pascal(project_name)}.Test.csproj")
@@ -971,7 +987,10 @@ class AvroToCSharp:
971
987
  avro_annotation=self.avro_annotation,
972
988
  system_xml_annotation=self.system_xml_annotation,
973
989
  system_text_json_annotation=self.system_text_json_annotation,
974
- newtonsoft_json_annotation=self.newtonsoft_json_annotation))
990
+ newtonsoft_json_annotation=self.newtonsoft_json_annotation,
991
+ NUNIT_VERSION=NUNIT_VERSION,
992
+ NUNIT_ADAPTER_VERSION=NUNIT_ADAPTER_VERSION,
993
+ MSTEST_SDK_VERSION=MSTEST_SDK_VERSION))
975
994
 
976
995
  self.output_dir = output_dir
977
996
  for avro_schema in (avs for avs in schema if isinstance(avs, dict)):
@@ -20,13 +20,13 @@
20
20
  <dependency>
21
21
  <groupId>org.junit.jupiter</groupId>
22
22
  <artifactId>junit-jupiter-api</artifactId>
23
- <version>5.10.0</version>
23
+ <version>{{ JUNIT_VERSION }}</version>
24
24
  <scope>test</scope>
25
25
  </dependency>
26
26
  <dependency>
27
27
  <groupId>org.junit.jupiter</groupId>
28
28
  <artifactId>junit-jupiter-engine</artifactId>
29
- <version>5.10.0</version>
29
+ <version>{{ JUNIT_VERSION }}</version>
30
30
  <scope>test</scope>
31
31
  </dependency>
32
32
  <dependency>
@@ -46,8 +46,9 @@
46
46
  <plugin>
47
47
  <groupId>org.apache.maven.plugins</groupId>
48
48
  <artifactId>maven-surefire-plugin</artifactId>
49
- <version>3.0.0-M9</version>
49
+ <version>{{ MAVEN_SUREFIRE_VERSION }}</version>
50
50
  </plugin>
51
51
  </plugins>
52
52
  </build>
53
53
  </project>
54
+
@@ -4,7 +4,8 @@
4
4
  import json
5
5
  import os
6
6
  from typing import Dict, List, Tuple, Union
7
- from avrotize.constants import AVRO_VERSION, JACKSON_VERSION, JDK_VERSION
7
+ from avrotize.constants import (AVRO_VERSION, JACKSON_VERSION, JDK_VERSION,
8
+ JUNIT_VERSION, MAVEN_COMPILER_VERSION, MAVEN_SUREFIRE_VERSION)
8
9
 
9
10
  from avrotize.common import pascal, camel, is_generic_avro_type, inline_avro_references, build_flat_type_dict
10
11
 
@@ -46,13 +47,13 @@ POM_CONTENT = """<?xml version="1.0" encoding="UTF-8"?>
46
47
  <dependency>
47
48
  <groupId>org.junit.jupiter</groupId>
48
49
  <artifactId>junit-jupiter-api</artifactId>
49
- <version>5.10.0</version>
50
+ <version>{JUNIT_VERSION}</version>
50
51
  <scope>test</scope>
51
52
  </dependency>
52
53
  <dependency>
53
54
  <groupId>org.junit.jupiter</groupId>
54
55
  <artifactId>junit-jupiter-engine</artifactId>
55
- <version>5.10.0</version>
56
+ <version>{JUNIT_VERSION}</version>
56
57
  <scope>test</scope>
57
58
  </dependency>
58
59
  </dependencies>
@@ -61,7 +62,7 @@ POM_CONTENT = """<?xml version="1.0" encoding="UTF-8"?>
61
62
  <plugin>
62
63
  <groupId>org.apache.maven.plugins</groupId>
63
64
  <artifactId>maven-compiler-plugin</artifactId>
64
- <version>3.11.0</version>
65
+ <version>{MAVEN_COMPILER_VERSION}</version>
65
66
  <configuration>
66
67
  <compilerArgs>
67
68
  <arg>-Xmaxerrs</arg>
@@ -72,7 +73,7 @@ POM_CONTENT = """<?xml version="1.0" encoding="UTF-8"?>
72
73
  <plugin>
73
74
  <groupId>org.apache.maven.plugins</groupId>
74
75
  <artifactId>maven-surefire-plugin</artifactId>
75
- <version>3.0.0-M9</version>
76
+ <version>{MAVEN_SUREFIRE_VERSION}</version>
76
77
  <configuration>
77
78
  <useSystemClassLoader>false</useSystemClassLoader>
78
79
  </configuration>
@@ -2092,7 +2093,16 @@ class AvroToJava:
2092
2093
  groupid = '.'.join(package_elements[:-1]) if len(package_elements) > 1 else package_elements[0]
2093
2094
  artifactid = package_elements[-1]
2094
2095
  with open(pom_path, 'w', encoding='utf-8') as file:
2095
- file.write(POM_CONTENT.format(groupid=groupid, artifactid=artifactid, AVRO_VERSION=AVRO_VERSION, JACKSON_VERSION=JACKSON_VERSION, JDK_VERSION=JDK_VERSION, PACKAGE=self.base_package))
2096
+ file.write(POM_CONTENT.format(
2097
+ groupid=groupid,
2098
+ artifactid=artifactid,
2099
+ AVRO_VERSION=AVRO_VERSION,
2100
+ JACKSON_VERSION=JACKSON_VERSION,
2101
+ JDK_VERSION=JDK_VERSION,
2102
+ JUNIT_VERSION=JUNIT_VERSION,
2103
+ MAVEN_COMPILER_VERSION=MAVEN_COMPILER_VERSION,
2104
+ MAVEN_SUREFIRE_VERSION=MAVEN_SUREFIRE_VERSION,
2105
+ PACKAGE=self.base_package))
2096
2106
  output_dir = os.path.join(
2097
2107
  output_dir, "src/main/java".replace('/', os.sep))
2098
2108
  if not os.path.exists(output_dir):
@@ -123,4 +123,16 @@ export class {{ class_name }} {
123
123
  }
124
124
  {%- endif %}
125
125
  {%- endif %}
126
+
127
+ /**
128
+ * Creates an instance of {{ class_name }} with sample data for testing.
129
+ * @returns A new {{ class_name }} instance with sample values.
130
+ */
131
+ public static createInstance(): {{ class_name }} {
132
+ return new {{ class_name }}(
133
+ {%- for field in fields %}
134
+ {{ field.test_value }}{% if not loop.last %},{% endif %} // {{ field.name }}
135
+ {%- endfor %}
136
+ );
137
+ }
126
138
  }
@@ -0,0 +1,77 @@
1
+ /** Test file for {{ class_name }} */
2
+ import { {{ class_name }} } from './{{ class_name }}.js';
3
+ {%- for import_type, import_path in imports.items() %}
4
+ import { {{ import_type }} } from '{{ import_path }}';
5
+ {%- endfor %}
6
+
7
+ describe('{{ class_name }}', () => {
8
+ let instance: {{ class_name }};
9
+
10
+ beforeEach(() => {
11
+ instance = {{ class_name }}.createInstance();
12
+ });
13
+
14
+ describe('createInstance', () => {
15
+ it('should create a valid instance', () => {
16
+ expect(instance).toBeInstanceOf({{ class_name }});
17
+ });
18
+
19
+ it('should create instances with consistent values', () => {
20
+ const instance1 = {{ class_name }}.createInstance();
21
+ const instance2 = {{ class_name }}.createInstance();
22
+ {%- for field in fields %}
23
+ expect(instance1.{{ field.name }}).toEqual(instance2.{{ field.name }});
24
+ {%- endfor %}
25
+ });
26
+ });
27
+
28
+ {%- for field in fields %}
29
+
30
+ describe('{{ field.name }} property', () => {
31
+ it('should have a valid {{ field.name }} value', () => {
32
+ expect(instance.{{ field.name }}).toBeDefined();
33
+ });
34
+
35
+ it('should accept assigned values', () => {
36
+ const testValue = {{ field.test_value }};
37
+ instance.{{ field.name }} = testValue;
38
+ expect(instance.{{ field.name }}).toEqual(testValue);
39
+ });
40
+ });
41
+ {%- endfor %}
42
+
43
+ {%- if typed_json_annotation %}
44
+
45
+ describe('JSON serialization', () => {
46
+ it('should serialize to JSON and deserialize back', () => {
47
+ const bytes = instance.toByteArray('application/json');
48
+ const restored = {{ class_name }}.fromData(bytes, 'application/json');
49
+ {%- for field in fields %}
50
+ expect(restored.{{ field.name }}).toEqual(instance.{{ field.name }});
51
+ {%- endfor %}
52
+ });
53
+
54
+ it('should match JSON structure', () => {
55
+ const jsonObj = {
56
+ {%- for field in fields %}
57
+ {{ field.original_name }}: instance.{{ field.name }}{% if not loop.last %},{% endif %}
58
+ {%- endfor %}
59
+ };
60
+ expect({{ class_name }}.isJsonMatch(jsonObj)).toBe(true);
61
+ });
62
+ });
63
+ {%- endif %}
64
+
65
+ {%- if avro_annotation %}
66
+
67
+ describe('Avro serialization', () => {
68
+ it('should serialize to Avro and deserialize back', () => {
69
+ const bytes = instance.toByteArray('application/vnd.apache.avro+avro');
70
+ const restored = {{ class_name }}.fromData(bytes, 'application/vnd.apache.avro+avro');
71
+ {%- for field in fields %}
72
+ expect(restored.{{ field.name }}).toEqual(instance.{{ field.name }});
73
+ {%- endfor %}
74
+ });
75
+ });
76
+ {%- endif %}
77
+ });
@@ -31,6 +31,7 @@ class AvroToTypeScript:
31
31
  self.output_dir = os.getcwd()
32
32
  self.src_dir = os.path.join(self.output_dir, "src")
33
33
  self.generated_types: Dict[str, str] = {}
34
+ self.generated_type_fields: Dict[str, List[Dict]] = {} # Store fields for test generation
34
35
  self.main_schema = None
35
36
  self.type_dict = None
36
37
  self.INDENT = ' ' * 4
@@ -160,6 +161,7 @@ class AvroToTypeScript:
160
161
  'is_array': field['definition']['is_array'],
161
162
  'is_union': field['definition']['is_union'],
162
163
  'docstring': field['docstring'],
164
+ 'test_value': self.generate_test_value(field['definition']['type'], field['definition']['is_enum']),
163
165
  } for field in fields]
164
166
 
165
167
  imports_with_paths: Dict[str, str] = {}
@@ -201,6 +203,7 @@ class AvroToTypeScript:
201
203
  if write_file:
202
204
  self.write_to_file(namespace, class_name, class_definition)
203
205
  self.generated_types[ts_qualified_name] = 'class'
206
+ self.generated_type_fields[ts_qualified_name] = fields # Store fields for test generation
204
207
  return ts_qualified_name
205
208
 
206
209
  def generate_enum(self, avro_schema: Dict, parent_namespace: str, write_file: bool = True) -> str:
@@ -242,6 +245,47 @@ class AvroToTypeScript:
242
245
  'is_enum': self.generated_types.get(import_name, '') == 'enum',
243
246
  }
244
247
 
248
+ def generate_test_value(self, field_type: str, is_enum: bool = False) -> str:
249
+ """Generate a test value for a TypeScript field type."""
250
+ # Strip nullable marker
251
+ is_nullable = field_type.endswith('?')
252
+ field_type = self.strip_nullable(field_type)
253
+
254
+ # Handle arrays
255
+ if field_type.endswith('[]'):
256
+ inner_type = field_type[:-2]
257
+ inner_value = self.generate_test_value(inner_type, is_enum)
258
+ return f'[{inner_value}]'
259
+
260
+ # Handle map/dict types
261
+ if field_type.startswith('{ [key: string]:'):
262
+ return "{ 'key': 'value' }"
263
+
264
+ # Handle union types (pipe-separated)
265
+ if '|' in field_type:
266
+ first_type = field_type.split('|')[0].strip()
267
+ return self.generate_test_value(first_type, is_enum)
268
+
269
+ # Handle enums - use first value (will be set via template)
270
+ if is_enum:
271
+ return f'{field_type}.values()[0]'
272
+
273
+ # Handle primitive types
274
+ primitive_values = {
275
+ 'string': "'sample-string'",
276
+ 'number': '42',
277
+ 'boolean': 'true',
278
+ 'null': 'null',
279
+ 'Date': "new Date('2024-01-01T00:00:00Z')",
280
+ 'any': "{ test: 'data' }",
281
+ }
282
+
283
+ if field_type in primitive_values:
284
+ return primitive_values[field_type]
285
+
286
+ # For complex types (classes), call their createInstance method
287
+ return f'{field_type}.createInstance()'
288
+
245
289
  def get_is_json_match_clause(self, field_name: str, field_type: str, field_is_enum: bool) -> str:
246
290
  """Generates the isJsonMatch clause for a field."""
247
291
  field_name_js = field_name.rstrip('_')
@@ -556,6 +600,57 @@ class AvroToTypeScript:
556
600
  with open(types_file_path, 'w', encoding='utf-8') as file:
557
601
  file.write(avro_js_types)
558
602
 
603
+ def generate_tests(self, output_dir: str):
604
+ """Generate Jest test files for all generated TypeScript classes."""
605
+ test_directory_path = os.path.join(output_dir, "test")
606
+ if not os.path.exists(test_directory_path):
607
+ os.makedirs(test_directory_path, exist_ok=True)
608
+
609
+ for qualified_name, type_kind in self.generated_types.items():
610
+ if type_kind == 'class':
611
+ self.generate_test_class(qualified_name, test_directory_path)
612
+
613
+ def generate_test_class(self, qualified_name: str, test_directory_path: str):
614
+ """Generate a Jest test file for a TypeScript class."""
615
+ parts = qualified_name.split('.')
616
+ class_name = parts[-1]
617
+ namespace = '.'.join(parts[:-1])
618
+ test_class_name = f"{class_name}.test"
619
+
620
+ fields = self.generated_type_fields.get(qualified_name, [])
621
+
622
+ # Build imports for nested types
623
+ imports_with_paths: Dict[str, str] = {}
624
+ for field in fields:
625
+ field_type = field.get('type_no_null', '')
626
+ if not self.is_typescript_primitive(field_type.replace('[]', '')):
627
+ # It's a reference type, need to import it
628
+ type_name = field_type.replace('[]', '').replace('?', '')
629
+ if type_name and type_name not in ['null', 'any', 'Date']:
630
+ # Build relative path from test dir to src dir
631
+ src_path = '/'.join(parts)
632
+ imports_with_paths[type_name] = f'../src/{src_path.rsplit("/", 1)[0]}/{type_name}.js' if '/' in src_path else f'../src/{parts[0]}/{type_name}.js'
633
+
634
+ # Calculate relative path from test directory to class file
635
+ class_path_parts = namespace.split('.') if namespace else []
636
+ relative_path = '../src/' + '/'.join(class_path_parts + [class_name]) + '.js'
637
+
638
+ test_definition = process_template(
639
+ "avrotots/class_test.ts.jinja",
640
+ class_name=class_name,
641
+ fields=fields,
642
+ imports=imports_with_paths,
643
+ typed_json_annotation=self.typed_json_annotation,
644
+ avro_annotation=self.avro_annotation,
645
+ )
646
+
647
+ # Update the import path in the generated test
648
+ test_definition = test_definition.replace(f"from './{class_name}.js'", f"from '{relative_path}'")
649
+
650
+ test_file_path = os.path.join(test_directory_path, f"{test_class_name}.ts")
651
+ with open(test_file_path, 'w', encoding='utf-8') as file:
652
+ file.write(test_definition)
653
+
559
654
  def convert_schema(self, schema: Union[List[Dict], Dict], output_dir: str, write_file: bool = True):
560
655
  """Convert Avro schema to TypeScript classes with namespace support."""
561
656
  self.output_dir = output_dir
@@ -571,6 +666,7 @@ class AvroToTypeScript:
571
666
  self.generate_enum(avro_schema, '', write_file)
572
667
  self.generate_index_file()
573
668
  self.generate_project_files(output_dir)
669
+ self.generate_tests(output_dir)
574
670
 
575
671
  def convert(self, avro_schema_path: str, output_dir: str):
576
672
  """Convert Avro schema to TypeScript classes."""