structurize 3.5.12__tar.gz → 3.6.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 (93) hide show
  1. {structurize-3.5.12/structurize.egg-info → structurize-3.6.0}/PKG-INFO +1 -1
  2. {structurize-3.5.12 → structurize-3.6.0}/avrotize/_version.py +3 -3
  3. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotokusto.py +19 -23
  4. {structurize-3.5.12 → structurize-3.6.0}/avrotize/common.py +46 -0
  5. {structurize-3.5.12 → structurize-3.6.0}/avrotize/dependencies/typescript/node22/package.json +1 -1
  6. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretocpp.py +14 -7
  7. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretocsharp.py +13 -11
  8. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretogo.py +6 -5
  9. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretojava.py +6 -5
  10. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretokusto.py +19 -23
  11. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretopython.py +7 -6
  12. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretorust.py +4 -5
  13. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretots.py +4 -3
  14. {structurize-3.5.12 → structurize-3.6.0/structurize.egg-info}/PKG-INFO +1 -1
  15. {structurize-3.5.12 → structurize-3.6.0}/.gitignore +0 -0
  16. {structurize-3.5.12 → structurize-3.6.0}/LICENSE +0 -0
  17. {structurize-3.5.12 → structurize-3.6.0}/MANIFEST.in +0 -0
  18. {structurize-3.5.12 → structurize-3.6.0}/README.md +0 -0
  19. {structurize-3.5.12 → structurize-3.6.0}/avrotize/__init__.py +0 -0
  20. {structurize-3.5.12 → structurize-3.6.0}/avrotize/__main__.py +0 -0
  21. {structurize-3.5.12 → structurize-3.6.0}/avrotize/asn1toavro.py +0 -0
  22. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotize.py +0 -0
  23. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotocpp.py +0 -0
  24. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotocsharp.py +0 -0
  25. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotocsv.py +0 -0
  26. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotodatapackage.py +0 -0
  27. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotodb.py +0 -0
  28. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotogo.py +0 -0
  29. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotographql.py +0 -0
  30. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotoiceberg.py +0 -0
  31. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotojava.py +0 -0
  32. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotojs.py +0 -0
  33. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotojsons.py +0 -0
  34. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotojstruct.py +0 -0
  35. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotomd.py +0 -0
  36. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotools.py +0 -0
  37. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotoparquet.py +0 -0
  38. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotoproto.py +0 -0
  39. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotopython.py +0 -0
  40. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotorust.py +0 -0
  41. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotots.py +0 -0
  42. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrototsml.py +0 -0
  43. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrotoxsd.py +0 -0
  44. {structurize-3.5.12 → structurize-3.6.0}/avrotize/avrovalidator.py +0 -0
  45. {structurize-3.5.12 → structurize-3.6.0}/avrotize/cddltostructure.py +0 -0
  46. {structurize-3.5.12 → structurize-3.6.0}/avrotize/choice_inference.py +0 -0
  47. {structurize-3.5.12 → structurize-3.6.0}/avrotize/commands.json +0 -0
  48. {structurize-3.5.12 → structurize-3.6.0}/avrotize/constants.py +0 -0
  49. {structurize-3.5.12 → structurize-3.6.0}/avrotize/csvtoavro.py +0 -0
  50. {structurize-3.5.12 → structurize-3.6.0}/avrotize/datapackagetoavro.py +0 -0
  51. {structurize-3.5.12 → structurize-3.6.0}/avrotize/dependencies/cpp/vcpkg/vcpkg.json +0 -0
  52. {structurize-3.5.12 → structurize-3.6.0}/avrotize/dependency_resolver.py +0 -0
  53. {structurize-3.5.12 → structurize-3.6.0}/avrotize/dependency_version.py +0 -0
  54. {structurize-3.5.12 → structurize-3.6.0}/avrotize/jsonstoavro.py +0 -0
  55. {structurize-3.5.12 → structurize-3.6.0}/avrotize/jsonstostructure.py +0 -0
  56. {structurize-3.5.12 → structurize-3.6.0}/avrotize/jsontoschema.py +0 -0
  57. {structurize-3.5.12 → structurize-3.6.0}/avrotize/jstructtoavro.py +0 -0
  58. {structurize-3.5.12 → structurize-3.6.0}/avrotize/kstructtoavro.py +0 -0
  59. {structurize-3.5.12 → structurize-3.6.0}/avrotize/kustotoavro.py +0 -0
  60. {structurize-3.5.12 → structurize-3.6.0}/avrotize/kustotojstruct.py +0 -0
  61. {structurize-3.5.12 → structurize-3.6.0}/avrotize/mcp_server.py +0 -0
  62. {structurize-3.5.12 → structurize-3.6.0}/avrotize/openapitostructure.py +0 -0
  63. {structurize-3.5.12 → structurize-3.6.0}/avrotize/parquettoavro.py +0 -0
  64. {structurize-3.5.12 → structurize-3.6.0}/avrotize/proto2parser.py +0 -0
  65. {structurize-3.5.12 → structurize-3.6.0}/avrotize/proto3parser.py +0 -0
  66. {structurize-3.5.12 → structurize-3.6.0}/avrotize/prototoavro.py +0 -0
  67. {structurize-3.5.12 → structurize-3.6.0}/avrotize/schema_inference.py +0 -0
  68. {structurize-3.5.12 → structurize-3.6.0}/avrotize/sqltoavro.py +0 -0
  69. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretocddl.py +0 -0
  70. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretocsv.py +0 -0
  71. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretodatapackage.py +0 -0
  72. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretodb.py +0 -0
  73. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretographql.py +0 -0
  74. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretoiceberg.py +0 -0
  75. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretojs.py +0 -0
  76. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretojsons.py +0 -0
  77. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretomd.py +0 -0
  78. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretoproto.py +0 -0
  79. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretotsml.py +0 -0
  80. {structurize-3.5.12 → structurize-3.6.0}/avrotize/structuretoxsd.py +0 -0
  81. {structurize-3.5.12 → structurize-3.6.0}/avrotize/tmslvalidate.py +0 -0
  82. {structurize-3.5.12 → structurize-3.6.0}/avrotize/validate.py +0 -0
  83. {structurize-3.5.12 → structurize-3.6.0}/avrotize/xmltoschema.py +0 -0
  84. {structurize-3.5.12 → structurize-3.6.0}/avrotize/xsdtoavro.py +0 -0
  85. {structurize-3.5.12 → structurize-3.6.0}/build.ps1 +0 -0
  86. {structurize-3.5.12 → structurize-3.6.0}/build.sh +0 -0
  87. {structurize-3.5.12 → structurize-3.6.0}/pyproject.toml +0 -0
  88. {structurize-3.5.12 → structurize-3.6.0}/setup.cfg +0 -0
  89. {structurize-3.5.12 → structurize-3.6.0}/structurize.egg-info/SOURCES.txt +0 -0
  90. {structurize-3.5.12 → structurize-3.6.0}/structurize.egg-info/dependency_links.txt +0 -0
  91. {structurize-3.5.12 → structurize-3.6.0}/structurize.egg-info/entry_points.txt +0 -0
  92. {structurize-3.5.12 → structurize-3.6.0}/structurize.egg-info/requires.txt +0 -0
  93. {structurize-3.5.12 → structurize-3.6.0}/structurize.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structurize
3
- Version: 3.5.12
3
+ Version: 3.6.0
4
4
  Summary: Tools to convert from and to JSON Structure from various other schema languages.
5
5
  Author-email: Clemens Vasters <clemensv@microsoft.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '3.5.12'
22
- __version_tuple__ = version_tuple = (3, 5, 12)
21
+ __version__ = version = '3.6.0'
22
+ __version_tuple__ = version_tuple = (3, 6, 0)
23
23
 
24
- __commit_id__ = commit_id = 'g0eb0a7b9d'
24
+ __commit_id__ = commit_id = 'g1329b8c45'
@@ -119,15 +119,13 @@ class AvroToKusto:
119
119
  # .create-or-alter table dfl_data_events ingestion json mapping
120
120
  kusto.append(
121
121
  f".create-or-alter table {table_ref} ingestion json mapping \"{mapping_base}_json_flat\"")
122
- kusto.append("```\n[")
122
+ mapping_entries = []
123
123
  if emit_cloudevents_columns:
124
- kusto.append(" {\"column\": \"___type\", \"path\": \"$.type\"},")
125
- kusto.append(
126
- " {\"column\": \"___source\", \"path\": \"$.source\"},")
127
- kusto.append(" {\"column\": \"___id\", \"path\": \"$.id\"},")
128
- kusto.append(" {\"column\": \"___time\", \"path\": \"$.time\"},")
129
- kusto.append(
130
- " {\"column\": \"___subject\", \"path\": \"$.subject\"},")
124
+ mapping_entries.append(" {\"column\": \"___type\", \"path\": \"$.type\"}")
125
+ mapping_entries.append(" {\"column\": \"___source\", \"path\": \"$.source\"}")
126
+ mapping_entries.append(" {\"column\": \"___id\", \"path\": \"$.id\"}")
127
+ mapping_entries.append(" {\"column\": \"___time\", \"path\": \"$.time\"}")
128
+ mapping_entries.append(" {\"column\": \"___subject\", \"path\": \"$.subject\"}")
131
129
  for field in fields:
132
130
  json_name = column_name = field["name"]
133
131
  if 'altnames' in field:
@@ -135,21 +133,19 @@ class AvroToKusto:
135
133
  column_name = field['altnames']['kql']
136
134
  if 'json' in field['altnames']:
137
135
  json_name = field['altnames']['json']
138
- kusto.append(
139
- f" {{\"column\": \"{column_name}\", \"path\": \"$.{json_name}\"}},")
140
- kusto.append("]\n```\n\n")
136
+ mapping_entries.append(
137
+ f" {{\"column\": \"{column_name}\", \"path\": \"$.{json_name}\"}}")
138
+ kusto.append("```\n[\n" + ",\n".join(mapping_entries) + "\n]\n```\n\n")
141
139
 
142
140
  if emit_cloudevents_columns:
143
141
  kusto.append(
144
142
  f".create-or-alter table {table_ref} ingestion json mapping \"{mapping_base}_json_ce_structured\"")
145
- kusto.append("```\n[")
146
- kusto.append(" {\"column\": \"___type\", \"path\": \"$.type\"},")
147
- kusto.append(
148
- " {\"column\": \"___source\", \"path\": \"$.source\"},")
149
- kusto.append(" {\"column\": \"___id\", \"path\": \"$.id\"},")
150
- kusto.append(" {\"column\": \"___time\", \"path\": \"$.time\"},")
151
- kusto.append(
152
- " {\"column\": \"___subject\", \"path\": \"$.subject\"},")
143
+ ce_entries = []
144
+ ce_entries.append(" {\"column\": \"___type\", \"path\": \"$.type\"}")
145
+ ce_entries.append(" {\"column\": \"___source\", \"path\": \"$.source\"}")
146
+ ce_entries.append(" {\"column\": \"___id\", \"path\": \"$.id\"}")
147
+ ce_entries.append(" {\"column\": \"___time\", \"path\": \"$.time\"}")
148
+ ce_entries.append(" {\"column\": \"___subject\", \"path\": \"$.subject\"}")
153
149
  for field in fields:
154
150
  json_name = column_name = field["name"]
155
151
  if 'altnames' in field:
@@ -157,9 +153,9 @@ class AvroToKusto:
157
153
  column_name = field['altnames']['kql']
158
154
  if 'json' in field['altnames']:
159
155
  json_name = field['altnames']['json']
160
- kusto.append(
161
- f" {{\"column\": \"{column_name}\", \"path\": \"$.data.{json_name}\"}},")
162
- kusto.append("]\n```\n\n")
156
+ ce_entries.append(
157
+ f" {{\"column\": \"{column_name}\", \"path\": \"$.data.{json_name}\"}}")
158
+ kusto.append("```\n[\n" + ",\n".join(ce_entries) + "\n]\n```\n\n")
163
159
 
164
160
  if emit_cloudevents_columns:
165
161
  kusto.append(
@@ -196,7 +192,7 @@ class AvroToKusto:
196
192
  kusto.append(
197
193
  f" \"Query\": \"{query}\",")
198
194
  kusto.append(" \"IsTransactional\": false,")
199
- kusto.append(" \"PropagateIngestionProperties\": true,")
195
+ kusto.append(" \"PropagateIngestionProperties\": true")
200
196
  kusto.append("}]")
201
197
  kusto.append("```\n")
202
198
 
@@ -830,6 +830,52 @@ def altname(schema_obj: dict, purpose: str):
830
830
  return schema_obj["name"]
831
831
 
832
832
 
833
+ def json_wire_name(prop_name: str, prop_schema: Any) -> str:
834
+ """
835
+ Resolve the JSON wire key for a property, honoring JSON Structure ``altnames.json``.
836
+
837
+ JSON Structure requires property keys to be identifiers. A non-identifier wire key
838
+ (e.g. ``dr-type``) is modeled as an identifier property name (``dr_type``) carrying
839
+ ``altnames: {"json": "dr-type"}``. The ``json`` purpose is the canonical wire name.
840
+
841
+ Args:
842
+ prop_name (str): The property name (identifier) used as the schema key.
843
+ prop_schema (Any): The property schema; may carry an ``altnames`` map.
844
+
845
+ Returns:
846
+ str: ``altnames.json`` when present, otherwise ``prop_name``.
847
+ """
848
+ if isinstance(prop_schema, dict):
849
+ altnames = prop_schema.get("altnames")
850
+ if isinstance(altnames, dict) and "json" in altnames:
851
+ return altnames["json"]
852
+ return prop_name
853
+
854
+
855
+ def json_enum_wire_value(value: Any, enum_schema: Any) -> str:
856
+ """
857
+ Resolve the JSON wire string for an enum value, honoring JSON Structure ``altenums.json``.
858
+
859
+ ``altenums.json`` is a map keyed by the original enum value; the language member name
860
+ stays derived from the original value, while the wire value uses the mapping when present.
861
+ Unmapped values serialize verbatim (identity fallback).
862
+
863
+ Args:
864
+ value: The original enum value (schema key).
865
+ enum_schema (Any): The enum schema; may carry an ``altenums`` map.
866
+
867
+ Returns:
868
+ str: ``altenums.json[value]`` when present, otherwise ``str(value)``.
869
+ """
870
+ if isinstance(enum_schema, dict):
871
+ altenums = enum_schema.get("altenums")
872
+ if isinstance(altenums, dict):
873
+ j = altenums.get("json")
874
+ if isinstance(j, dict) and str(value) in j:
875
+ return j[str(value)]
876
+ return str(value)
877
+
878
+
833
879
  def process_template(file_path: str, **kvargs) -> str:
834
880
  """
835
881
  Process a file as a Jinja2 template with the given object as input.
@@ -8,7 +8,7 @@
8
8
  "kafkajs": "^2.2.4"
9
9
  },
10
10
  "devDependencies": {
11
- "@types/node": "^25.0.3",
11
+ "@types/node": "^26.0.0",
12
12
  "typescript": "^6.0.2",
13
13
  "jest": "^30.2.0",
14
14
  "@types/jest": "^30.0.0"
@@ -5,7 +5,7 @@ import json
5
5
  import os
6
6
  from typing import Dict, List, Union, Set, Optional, Any, cast
7
7
 
8
- from avrotize.common import pascal, process_template
8
+ from avrotize.common import pascal, process_template, json_wire_name, json_enum_wire_value
9
9
 
10
10
  INDENT = ' '
11
11
 
@@ -307,9 +307,10 @@ class StructureToCpp:
307
307
  source_type = 'object'
308
308
  else:
309
309
  source_type = 'object'
310
- all_field_info.append((field_name, prop_name, field_type, source_type))
310
+ wire_name = json_wire_name(prop_name, prop_schema)
311
+ all_field_info.append((field_name, wire_name, field_type, source_type))
311
312
  if source_type in ('int64', 'uint64', 'int128', 'uint128', 'decimal'):
312
- string_json_fields.append((field_name, prop_name, field_type, source_type))
313
+ string_json_fields.append((field_name, wire_name, field_type, source_type))
313
314
 
314
315
  # Add documentation
315
316
  if 'description' in prop_schema or 'doc' in prop_schema:
@@ -330,8 +331,10 @@ class StructureToCpp:
330
331
  if self.json_annotation:
331
332
  class_definition += self.generate_to_json_method(class_name)
332
333
 
333
- # Add custom nlohmann to_json/from_json if we have string-serialized numeric fields
334
- if self.json_annotation and string_json_fields:
334
+ # Add custom nlohmann to_json/from_json if we have string-serialized numeric
335
+ # fields or any field whose JSON wire key differs from the C++ member name
336
+ has_renamed_fields = any(o != f for f, o, _, _ in all_field_info)
337
+ if self.json_annotation and (string_json_fields or has_renamed_fields):
335
338
  class_definition += f"\n{INDENT}friend void to_json(nlohmann::json& j, const {class_name}& v) {{\n"
336
339
  class_definition += f"{INDENT}{INDENT}j = nlohmann::json::object();\n"
337
340
  for fname, orig_name, ftype, stype in all_field_info:
@@ -394,10 +397,14 @@ class StructureToCpp:
394
397
  enum_definition += f"// {doc}\n"
395
398
 
396
399
  symbols = structure_schema.get('enum', [])
400
+ members = [(self.safe_identifier(str(s)), json_enum_wire_value(s, structure_schema)) for s in symbols]
397
401
  enum_definition += f"enum class {enum_name} {{\n"
398
- for symbol in symbols:
399
- enum_definition += f"{INDENT}{self.safe_identifier(str(symbol))},\n"
402
+ for name, _ in members:
403
+ enum_definition += f"{INDENT}{name},\n"
400
404
  enum_definition += "};\n\n"
405
+ if members:
406
+ pairs = ", ".join(f'{{{enum_name}::{name}, "{wire}"}}' for name, wire in members)
407
+ enum_definition += f"NLOHMANN_JSON_SERIALIZE_ENUM({enum_name}, {{ {pairs} }})\n\n"
401
408
 
402
409
  if write_file:
403
410
  self.write_to_file(namespace, enum_name, "", enum_definition)
@@ -8,7 +8,7 @@ import re
8
8
  from typing import Any, Dict, List, Tuple, Union, cast, Optional
9
9
  import uuid
10
10
 
11
- from avrotize.common import pascal, process_template
11
+ from avrotize.common import pascal, process_template, json_wire_name, json_enum_wire_value
12
12
  from avrotize.jstructtoavro import JsonStructureToAvro
13
13
  from avrotize.constants import (
14
14
  NEWTONSOFT_JSON_VERSION,
@@ -479,8 +479,9 @@ class StructureToCSharp:
479
479
  else:
480
480
  field_name_cs = field_name
481
481
 
482
- # Track if field name differs from original for JSON annotation
483
- needs_json_annotation = field_name_cs != prop_name
482
+ # JSON wire key honors JSON Structure altnames.json; annotate when it differs
483
+ wire_name = json_wire_name(prop_name, prop_schema)
484
+ needs_json_annotation = field_name_cs != wire_name
484
485
 
485
486
  # Check if this is a const field
486
487
  if 'const' in prop_schema:
@@ -498,9 +499,9 @@ class StructureToCSharp:
498
499
  # Add JSON property name annotation when property name differs from schema name
499
500
  # This is needed for proper JSON serialization/deserialization, especially with pascal_properties
500
501
  if needs_json_annotation:
501
- property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{prop_name}")]\n'
502
+ property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{wire_name}")]\n'
502
503
  if self.newtonsoft_json_annotation and needs_json_annotation:
503
- property_definition += f'{INDENT}[Newtonsoft.Json.JsonProperty("{prop_name}")]\n'
504
+ property_definition += f'{INDENT}[Newtonsoft.Json.JsonProperty("{wire_name}")]\n'
504
505
 
505
506
  # Add XML element annotation if enabled
506
507
  if self.system_xml_annotation:
@@ -533,9 +534,9 @@ class StructureToCSharp:
533
534
  # Add JSON property name annotation when property name differs from schema name
534
535
  # This is needed for proper JSON serialization/deserialization, especially with pascal_properties
535
536
  elif needs_json_annotation:
536
- property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{prop_name}")]\n'
537
+ property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{wire_name}")]\n'
537
538
  if self.newtonsoft_json_annotation and needs_json_annotation:
538
- property_definition += f'{INDENT}[Newtonsoft.Json.JsonProperty("{prop_name}")]\n'
539
+ property_definition += f'{INDENT}[Newtonsoft.Json.JsonProperty("{wire_name}")]\n'
539
540
 
540
541
  # Add XML element annotation if enabled
541
542
  if self.system_xml_annotation:
@@ -765,7 +766,7 @@ class StructureToCSharp:
765
766
  enum_definition += f"{INDENT*2}{{\n"
766
767
  for value in enum_values:
767
768
  member_name = pascal(str(value).replace('-', '_').replace(' ', '_'))
768
- enum_definition += f'{INDENT*3}"{value}" => {enum_name}.{member_name},\n'
769
+ enum_definition += f'{INDENT*3}"{json_enum_wire_value(value, structure_schema)}" => {enum_name}.{member_name},\n'
769
770
  enum_definition += f'{INDENT*3}_ => throw new System.Text.Json.JsonException($"Unknown value \'{{stringValue}}\' for {enum_name}")\n'
770
771
  enum_definition += f"{INDENT*2}}};\n"
771
772
 
@@ -783,7 +784,7 @@ class StructureToCSharp:
783
784
  enum_definition += f"{INDENT*2}{{\n"
784
785
  for value in enum_values:
785
786
  member_name = pascal(str(value).replace('-', '_').replace(' ', '_'))
786
- enum_definition += f'{INDENT*3}{enum_name}.{member_name} => "{value}",\n'
787
+ enum_definition += f'{INDENT*3}{enum_name}.{member_name} => "{json_enum_wire_value(value, structure_schema)}",\n'
787
788
  enum_definition += f'{INDENT*3}_ => throw new System.ArgumentOutOfRangeException(nameof(value))\n'
788
789
  enum_definition += f"{INDENT*2}}};\n"
789
790
  enum_definition += f"{INDENT*2}writer.WriteStringValue(stringValue);\n"
@@ -813,7 +814,7 @@ class StructureToCSharp:
813
814
  enum_definition += f"{INDENT*2}{{\n"
814
815
  for value in enum_values:
815
816
  member_name = pascal(str(value).replace('-', '_').replace(' ', '_'))
816
- enum_definition += f'{INDENT*3}"{value}" => {enum_name}.{member_name},\n'
817
+ enum_definition += f'{INDENT*3}"{json_enum_wire_value(value, structure_schema)}" => {enum_name}.{member_name},\n'
817
818
  enum_definition += f'{INDENT*3}_ => throw new Newtonsoft.Json.JsonException($"Unknown value \'{{stringValue}}\' for {enum_name}")\n'
818
819
  enum_definition += f"{INDENT*2}}};\n"
819
820
 
@@ -831,7 +832,7 @@ class StructureToCSharp:
831
832
  enum_definition += f"{INDENT*2}{{\n"
832
833
  for value in enum_values:
833
834
  member_name = pascal(str(value).replace('-', '_').replace(' ', '_'))
834
- enum_definition += f'{INDENT*3}{enum_name}.{member_name} => "{value}",\n'
835
+ enum_definition += f'{INDENT*3}{enum_name}.{member_name} => "{json_enum_wire_value(value, structure_schema)}",\n'
835
836
  enum_definition += f'{INDENT*3}_ => throw new System.ArgumentOutOfRangeException(nameof(value))\n'
836
837
  enum_definition += f"{INDENT*2}}};\n"
837
838
  enum_definition += f"{INDENT*2}writer.WriteValue(stringValue);\n"
@@ -2444,3 +2445,4 @@ def convert_structure_schema_to_csharp(
2444
2445
  structtocs.system_xml_annotation = system_xml_annotation
2445
2446
  structtocs.avro_annotation = avro_annotation
2446
2447
  structtocs.convert_schema(structure_schema, output_dir)
2448
+
@@ -6,7 +6,7 @@ import json
6
6
  import os
7
7
  from typing import Any, Dict, List, Set, Union, Optional, cast
8
8
 
9
- from avrotize.common import pascal, render_template
9
+ from avrotize.common import pascal, render_template, json_wire_name, json_enum_wire_value
10
10
 
11
11
  JsonNode = Dict[str, 'JsonNode'] | List['JsonNode'] | str | None
12
12
 
@@ -341,7 +341,7 @@ class StructureToGo:
341
341
  fields.append({
342
342
  'name': pascal(prop_name),
343
343
  'type': field_type,
344
- 'original_name': prop_name,
344
+ 'original_name': json_wire_name(prop_name, prop_schema),
345
345
  'source_type': source_type
346
346
  })
347
347
 
@@ -401,7 +401,8 @@ class StructureToGo:
401
401
  self.generated_types[go_enum_name] = "enum"
402
402
  self.generated_structure_types[go_enum_name] = structure_schema
403
403
 
404
- symbols = structure_schema.get('enum', [])
404
+ raw_symbols = structure_schema.get('enum', [])
405
+ symbols = [{'name': str(s), 'value': json_enum_wire_value(s, structure_schema)} for s in raw_symbols]
405
406
 
406
407
  # Determine base type
407
408
  base_type = structure_schema.get('type', 'string')
@@ -423,10 +424,10 @@ class StructureToGo:
423
424
 
424
425
  self.enums.append({
425
426
  'name': go_enum_name,
426
- 'symbols': symbols,
427
+ 'symbols': [s['name'] for s in symbols],
427
428
  })
428
429
 
429
- self.generate_unit_test('enum', go_enum_name, symbols)
430
+ self.generate_unit_test('enum', go_enum_name, [s['name'] for s in symbols])
430
431
 
431
432
  return go_enum_name
432
433
 
@@ -6,7 +6,7 @@ import os
6
6
  from typing import Dict, List, Tuple, Union, Set, Optional, Any
7
7
  from avrotize.constants import JACKSON_VERSION, JACKSON_ANNOTATIONS_VERSION
8
8
 
9
- from avrotize.common import pascal, camel, process_template
9
+ from avrotize.common import pascal, camel, process_template, json_wire_name, json_enum_wire_value
10
10
 
11
11
  INDENT = ' '
12
12
 
@@ -446,7 +446,7 @@ class StructureToJava:
446
446
  source_type = 'object'
447
447
  return {
448
448
  'name': safe_field_name,
449
- 'original_name': prop_name,
449
+ 'original_name': json_wire_name(prop_name, prop_schema),
450
450
  'type': field_type.type_name,
451
451
  'source_type': source_type,
452
452
  'docstring': doc,
@@ -611,15 +611,16 @@ class StructureToJava:
611
611
  symbols=symbol_list
612
612
  )
613
613
  else:
614
- # String enum
615
- safe_symbols = [self.safe_identifier(pascal(str(symbol).replace('-', '_').replace(' ', '_'))) for symbol in symbols]
614
+ # String enum — member name from original value; JSON wire value via altenums.json
615
+ symbol_list = [{'name': self.safe_identifier(pascal(str(symbol).replace('-', '_').replace(' ', '_'))),
616
+ 'value': json_enum_wire_value(symbol, structure_schema)} for symbol in symbols]
616
617
  enum_definition = process_template(
617
618
  "structuretojava/enum_core.jinja",
618
619
  class_name=enum_name,
619
620
  docstring=doc,
620
621
  deprecated=deprecated,
621
622
  is_numeric=False,
622
- symbols=safe_symbols
623
+ symbols=symbol_list
623
624
  )
624
625
 
625
626
  if write_file:
@@ -352,43 +352,39 @@ class StructureToKusto:
352
352
  # add the JSON mapping for the table
353
353
  kusto.append(
354
354
  f".create-or-alter table {table_ref} ingestion json mapping \"{mapping_base}_json_flat\"")
355
- kusto.append("```\n[")
355
+ mapping_entries = []
356
356
  if emit_cloudevents_columns:
357
- kusto.append(" {\"column\": \"___type\", \"path\": \"$.type\"},")
358
- kusto.append(
359
- " {\"column\": \"___source\", \"path\": \"$.source\"},")
360
- kusto.append(" {\"column\": \"___id\", \"path\": \"$.id\"},")
361
- kusto.append(" {\"column\": \"___time\", \"path\": \"$.time\"},")
362
- kusto.append(
363
- " {\"column\": \"___subject\", \"path\": \"$.subject\"},")
357
+ mapping_entries.append(" {\"column\": \"___type\", \"path\": \"$.type\"}")
358
+ mapping_entries.append(" {\"column\": \"___source\", \"path\": \"$.source\"}")
359
+ mapping_entries.append(" {\"column\": \"___id\", \"path\": \"$.id\"}")
360
+ mapping_entries.append(" {\"column\": \"___time\", \"path\": \"$.time\"}")
361
+ mapping_entries.append(" {\"column\": \"___subject\", \"path\": \"$.subject\"}")
364
362
  for prop_name, prop_schema in properties.items():
365
363
  # Skip const fields in JSON mapping since they're not stored as columns
366
364
  if isinstance(prop_schema, dict) and 'const' in prop_schema:
367
365
  continue
368
366
  column_name = prop_name
369
- kusto.append(
370
- f" {{\"column\": \"{column_name}\", \"path\": \"$.{prop_name}\"}},")
371
- kusto.append("]\n```\n\n")
367
+ mapping_entries.append(
368
+ f" {{\"column\": \"{column_name}\", \"path\": \"$.{prop_name}\"}}")
369
+ kusto.append("```\n[\n" + ",\n".join(mapping_entries) + "\n]\n```\n\n")
372
370
 
373
371
  if emit_cloudevents_columns:
374
372
  kusto.append(
375
373
  f".create-or-alter table {table_ref} ingestion json mapping \"{mapping_base}_json_ce_structured\"")
376
- kusto.append("```\n[")
377
- kusto.append(" {\"column\": \"___type\", \"path\": \"$.type\"},")
378
- kusto.append(
379
- " {\"column\": \"___source\", \"path\": \"$.source\"},")
380
- kusto.append(" {\"column\": \"___id\", \"path\": \"$.id\"},")
381
- kusto.append(" {\"column\": \"___time\", \"path\": \"$.time\"},")
382
- kusto.append(
383
- " {\"column\": \"___subject\", \"path\": \"$.subject\"},")
374
+ ce_entries = []
375
+ ce_entries.append(" {\"column\": \"___type\", \"path\": \"$.type\"}")
376
+ ce_entries.append(" {\"column\": \"___source\", \"path\": \"$.source\"}")
377
+ ce_entries.append(" {\"column\": \"___id\", \"path\": \"$.id\"}")
378
+ ce_entries.append(" {\"column\": \"___time\", \"path\": \"$.time\"}")
379
+ ce_entries.append(" {\"column\": \"___subject\", \"path\": \"$.subject\"}")
384
380
  for prop_name, prop_schema in properties.items():
385
381
  # Skip const fields in JSON mapping since they're not stored as columns
386
382
  if isinstance(prop_schema, dict) and 'const' in prop_schema:
387
383
  continue
388
384
  column_name = prop_name
389
- kusto.append(
390
- f" {{\"column\": \"{column_name}\", \"path\": \"$.data.{prop_name}\"}},")
391
- kusto.append("]\n```\n\n")
385
+ ce_entries.append(
386
+ f" {{\"column\": \"{column_name}\", \"path\": \"$.data.{prop_name}\"}}")
387
+ kusto.append("```\n[\n" + ",\n".join(ce_entries) + "\n]\n```\n\n")
392
388
 
393
389
  if emit_cloudevents_columns:
394
390
  kusto.append(
@@ -421,7 +417,7 @@ class StructureToKusto:
421
417
  kusto.append(
422
418
  f" \"Query\": \"{query}\",")
423
419
  kusto.append(" \"IsTransactional\": false,")
424
- kusto.append(" \"PropagateIngestionProperties\": true,")
420
+ kusto.append(" \"PropagateIngestionProperties\": true")
425
421
  kusto.append("}]")
426
422
  kusto.append("```\n")
427
423
 
@@ -8,7 +8,7 @@ import re
8
8
  import random
9
9
  from typing import Any, Dict, List, Set, Tuple, Union, Optional
10
10
 
11
- from avrotize.common import pascal, process_template
11
+ from avrotize.common import pascal, process_template, json_wire_name, json_enum_wire_value
12
12
  from avrotize.jstructtoavro import JsonStructureToAvro
13
13
 
14
14
  JsonNode = Dict[str, 'JsonNode'] | List['JsonNode'] | str | None
@@ -437,8 +437,9 @@ class StructureToPython:
437
437
  """ Generates a field for a Python dataclass """
438
438
  # Sanitize field name for Python identifier validity
439
439
  field_name = self.safe_identifier(prop_name, class_name)
440
- # Track if we need a field_name annotation for JSON serialization
441
- needs_field_name_annotation = field_name != prop_name
440
+ # Wire key honors JSON Structure altnames.json; annotation needed when it differs
441
+ wire_name = json_wire_name(prop_name, prop_schema)
442
+ needs_field_name_annotation = wire_name != field_name
442
443
 
443
444
  # Check if this is a const field
444
445
  if 'const' in prop_schema:
@@ -447,7 +448,7 @@ class StructureToPython:
447
448
  class_name, field_name, prop_schema, parent_namespace, import_types)
448
449
  return {
449
450
  'name': field_name,
450
- 'json_name': prop_name if needs_field_name_annotation else None,
451
+ 'json_name': wire_name if needs_field_name_annotation else None,
451
452
  'type': prop_type,
452
453
  'is_primitive': self.is_python_primitive(prop_type) or self.is_python_typing_struct(prop_type),
453
454
  'is_enum': False,
@@ -482,7 +483,7 @@ class StructureToPython:
482
483
 
483
484
  return {
484
485
  'name': field_name,
485
- 'json_name': prop_name if needs_field_name_annotation else None,
486
+ 'json_name': wire_name if needs_field_name_annotation else None,
486
487
  'type': prop_type,
487
488
  'is_primitive': self.is_python_primitive(prop_type) or self.is_python_typing_struct(prop_type),
488
489
  'is_enum': prop_type in self.generated_types and self.generated_types[prop_type] == 'enum',
@@ -612,7 +613,7 @@ class StructureToPython:
612
613
  if is_numeric:
613
614
  value_repr = repr(value)
614
615
  else:
615
- value_repr = repr(str(value))
616
+ value_repr = repr(json_enum_wire_value(value, structure_schema))
616
617
  members.append((member_name, value_repr))
617
618
  symbols.append(member_name)
618
619
 
@@ -7,7 +7,7 @@ import os
7
7
  import re
8
8
  from typing import Any, Dict, List, Set, Tuple, Union, Optional
9
9
 
10
- from avrotize.common import pascal, snake, render_template
10
+ from avrotize.common import pascal, snake, render_template, json_wire_name, json_enum_wire_value
11
11
 
12
12
  JsonNode = Dict[str, 'JsonNode'] | List['JsonNode'] | str | None
13
13
 
@@ -307,7 +307,7 @@ class StructureToRust:
307
307
  if 'const' in prop_schema:
308
308
  continue
309
309
 
310
- original_field_name = prop_name
310
+ original_field_name = json_wire_name(prop_name, prop_schema)
311
311
  field_name = self.safe_identifier(snake(prop_name))
312
312
 
313
313
  # Determine if required
@@ -382,12 +382,11 @@ class StructureToRust:
382
382
  # Convert enum values to valid Rust identifiers
383
383
  symbols = []
384
384
  for value in enum_values:
385
+ wire = json_enum_wire_value(value, structure_schema)
385
386
  if isinstance(value, str):
386
- # Convert to PascalCase and make it a valid Rust identifier
387
387
  symbol = pascal(value.replace('-', '_').replace(' ', '_'))
388
- symbols.append({'name': symbol, 'value': value})
388
+ symbols.append({'name': symbol, 'value': wire})
389
389
  else:
390
- # For numeric values, use Value prefix
391
390
  symbols.append({'name': f"Value{value}", 'value': str(value)})
392
391
 
393
392
  doc = structure_schema.get('description', structure_schema.get('doc', enum_name))
@@ -8,7 +8,7 @@ import random
8
8
  import re
9
9
  from typing import Any, Dict, List, Set, Tuple, Union, Optional
10
10
 
11
- from avrotize.common import pascal, process_template
11
+ from avrotize.common import pascal, process_template, json_wire_name, json_enum_wire_value
12
12
 
13
13
  JsonNode = Dict[str, 'JsonNode'] | List['JsonNode'] | str | None
14
14
 
@@ -356,7 +356,7 @@ class StructureToTypeScript:
356
356
  source_type = 'object'
357
357
  fields.append({
358
358
  'name': self.safe_name(prop_name),
359
- 'original_name': prop_name,
359
+ 'original_name': json_wire_name(prop_name, prop_schema),
360
360
  'type': field_type,
361
361
  'type_no_null': field_type_no_null,
362
362
  'source_type': source_type,
@@ -421,7 +421,8 @@ class StructureToTypeScript:
421
421
  if typescript_qualified_name in self.generated_types:
422
422
  return typescript_qualified_name
423
423
 
424
- symbols = structure_schema.get('enum', [])
424
+ raw_symbols = structure_schema.get('enum', [])
425
+ symbols = [{'name': str(s), 'value': json_enum_wire_value(s, structure_schema)} for s in raw_symbols]
425
426
 
426
427
  enum_definition = process_template(
427
428
  "structuretots/enum_core.ts.jinja",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structurize
3
- Version: 3.5.12
3
+ Version: 3.6.0
4
4
  Summary: Tools to convert from and to JSON Structure from various other schema languages.
5
5
  Author-email: Clemens Vasters <clemensv@microsoft.com>
6
6
  Classifier: Programming Language :: Python :: 3
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes