Skip to content

Commit

Permalink
escape dictionary keys when serializing
Browse files Browse the repository at this point in the history
add tests to ensure affected characters are properly serialized when encoding json record structures
  • Loading branch information
joshmossas committed Oct 16, 2024
1 parent 26fe9e1 commit 296de1c
Show file tree
Hide file tree
Showing 23 changed files with 97 additions and 47 deletions.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"dart-code.dart-code",
"dart-code.flutter",
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml"
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ data class ObjectWithEveryType(
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += __entry.value
}
output += "}"
Expand Down Expand Up @@ -1173,7 +1173,7 @@ data class ObjectWithOptionalFields(
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += __entry.value
}
output += "}"
Expand Down Expand Up @@ -1497,7 +1497,7 @@ data class ObjectWithNullableFields(
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += __entry.value
}
output += "}"
Expand Down
4 changes: 2 additions & 2 deletions languages/kotlin/kotlin-codegen/src/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function kotlinMapFromSchema(
if (__index != 0) {
${target} += ","
}
${target} += "\\"\${__entry.key}\\":"
${target} += "\${buildString { printQuoted(__entry.key) }}:"
${subType.toJson("__entry.value", target)}
}
${target} += "}"
Expand All @@ -61,7 +61,7 @@ export function kotlinMapFromSchema(
if (__index != 0) {
${target} += ","
}
${target} += "\\"\${__entry.key}\\":"
${target} += "\${buildString { printQuoted(__entry.key) }}:"
${subType.toJson("__entry.value", target)}
}
${target} += "}"`;
Expand Down
6 changes: 3 additions & 3 deletions languages/rust/rust-codegen-reference/src/example_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ impl ArriModel for ObjectWithEveryType {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(_value_.to_string().as_str());
}
_json_output_.push('}');
Expand Down Expand Up @@ -1247,7 +1247,7 @@ impl ArriModel for ObjectWithOptionalFields {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(_value_.to_string().as_str());
}
_json_output_.push('}');
Expand Down Expand Up @@ -1796,7 +1796,7 @@ impl ArriModel for ObjectWithNullableFields {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(_value_.to_string().as_str());
}
_json_output_.push('}');
Expand Down
4 changes: 2 additions & 2 deletions languages/rust/rust-codegen/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default function rustRecordFromSchema(
if _index_ != 0 {
${target}.push(',');
}
${target}.push_str(format!("\\"{}\\":", _key_).as_str());
${target}.push_str(format!("{}:", serialize_string(_key_)).as_str());
match _value_ {
Some(value_val) => {
${innerType.toJsonTemplate("value_val", target)};
Expand All @@ -84,7 +84,7 @@ export default function rustRecordFromSchema(
if _index_ != 0 {
${target}.push(',');
}
${target}.push_str(format!("\\"{}\\":", _key_).as_str());
${target}.push_str(format!("{}:", serialize_string(_key_)).as_str());
${innerType.toJsonTemplate(`_value_`, target)};
}
${target}.push('}')`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ public struct ObjectWithEveryType: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += "\(__value)"
}
__json += "}"
Expand Down Expand Up @@ -1094,7 +1094,7 @@ public struct ObjectWithOptionalFields: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += "\(__value)"
}
__json += "}"
Expand Down Expand Up @@ -1471,7 +1471,7 @@ public struct ObjectWithNullableFields: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += "\(__value)"
}
__json += "}"
Expand Down
2 changes: 1 addition & 1 deletion languages/swift/swift-codegen/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ ${mainContent}
if __index > 0 {
${target} += ","
}
${target} += "\\"\\(__key)\\":"
${target} += "\\(serializeString(input: __key)):"
${subType.toJsonTemplate("__value", target)}
}
${target} += "}"`;
Expand Down
6 changes: 3 additions & 3 deletions languages/ts/ts-codegen-reference/src/referenceClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ export const $$ObjectWithEveryType: ArriModelValidator<ObjectWithEveryType> = {
if (_recordPropertyCount !== 0) {
json += ",";
}
json += `"${_key}":`;
json += `${serializeString(_key)}:`;
json += `${_value}`;
_recordPropertyCount++;
}
Expand Down Expand Up @@ -1455,7 +1455,7 @@ export const $$ObjectWithOptionalFields: ArriModelValidator<ObjectWithOptionalFi
if (_recordPropertyCount !== 0) {
json += ",";
}
json += `"${_key}":`;
json += `${serializeString(_key)}:`;
json += `${_value}`;
_recordPropertyCount++;
}
Expand Down Expand Up @@ -1933,7 +1933,7 @@ export const $$ObjectWithNullableFields: ArriModelValidator<ObjectWithNullableFi
if (_recordPropertyCount !== 0) {
json += ",";
}
json += `"${_key}":`;
json += `${serializeString(_key)}:`;
json += `${_value}`;
_recordPropertyCount++;
}
Expand Down
1 change: 1 addition & 0 deletions languages/ts/ts-codegen/src/_index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AppDefinition, normalizeWhitespace } from "@arrirpc/codegen-utils";
import fs from "fs";
import path from "path";
import { expect, test } from "vitest";

import { createTypescriptClient } from "./_index";

Expand Down
4 changes: 2 additions & 2 deletions languages/ts/ts-codegen/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function tsRecordFromSchema(
if (${countVal} !== 0) {
${target} += ',';
}
${target} += \`"\${_key}":\`;
${target} += \`\${serializeString(_key)}:\`;
${innerType.toJsonTemplate("_value", target, "_key")}
${countVal}++;
}
Expand All @@ -70,7 +70,7 @@ export function tsRecordFromSchema(
if (${countVal} !== 0) {
${target} += ',';
}
${target} += \`"\${_key}":\`;
${target} += \`\${serializeString(_key)}:\`;
${innerType.toJsonTemplate("_value", target, "_key")};
${countVal}++;
}
Expand Down
1 change: 1 addition & 0 deletions tests/clients/dart/test/test_client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Future<void> main() async {
record: {
"A": BigInt.from(1),
"B": BigInt.from(0),
"\"C\"\t": BigInt.from(1),
},
discriminator: ObjectWithEveryTypeDiscriminatorA(title: "Hello World"),
nestedObject: ObjectWithEveryTypeNestedObject(
Expand Down
2 changes: 1 addition & 1 deletion tests/clients/kotlin/src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fun main() {
)
)
),
record = mutableMapOf(Pair("01", 1UL), Pair("02", 0UL)),
record = mutableMapOf(Pair("01", 1UL), Pair("02", 0UL), Pair("\"03\"\t", 1UL)),
nestedObject = ObjectWithEveryTypeNestedObject(
id = "d1", timestamp = targetDate, data = ObjectWithEveryTypeNestedObjectData(
id = "d2", timestamp = targetDate, data = ObjectWithEveryTypeNestedObjectDataData(
Expand Down
10 changes: 5 additions & 5 deletions tests/clients/kotlin/src/main/kotlin/TestClient.rpc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ output += "{"
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += "\"${__entry.value}\""
}
output += "}"
Expand Down Expand Up @@ -1840,7 +1840,7 @@ if (record == null) {
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += when (__entry.value) {
is ULong -> "\"${__entry.value}\""
else -> "null"
Expand Down Expand Up @@ -2899,7 +2899,7 @@ if (record != null) {
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += "\"${__entry.value}\""
}
output += "}"
Expand Down Expand Up @@ -5512,7 +5512,7 @@ output += "{"
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += __entry.value.toJson()
}
output += "}"
Expand All @@ -5522,7 +5522,7 @@ output += "{"
if (__index != 0) {
output += ","
}
output += "\"${__entry.key}\":"
output += "${buildString { printQuoted(__entry.key) }}:"
output += JsonInstance.encodeToString(__entry.value)
}
output += "}"
Expand Down
1 change: 1 addition & 0 deletions tests/clients/rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ mod tests {
let mut record = BTreeMap::<String, u64>::new();
record.insert("A".to_string(), 1);
record.insert("B".to_string(), 0);
record.insert("\"C\"\t".to_string(), 1);
let mut input = ObjectWithEveryType {
any: serde_json::Value::String("hello world".to_string()),
boolean: true,
Expand Down
10 changes: 5 additions & 5 deletions tests/clients/rust/src/test_client.g.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ impl ArriModel for ObjectWithEveryType {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(format!("\"{}\"", _value_).as_str());
}
_json_output_.push('}');
Expand Down Expand Up @@ -1964,7 +1964,7 @@ impl ArriModel for ObjectWithEveryNullableType {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
match _value_ {
Some(value_val) => {
_json_output_.push_str(format!("\"{}\"", value_val).as_str());
Expand Down Expand Up @@ -3365,7 +3365,7 @@ impl ArriModel for ObjectWithEveryOptionalType {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(format!("\"{}\"", _value_).as_str());
}
_json_output_.push('}');
Expand Down Expand Up @@ -5514,7 +5514,7 @@ impl ArriModel for UsersWatchUserResponse {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(_value_.to_json_string().as_str());
}
_json_output_.push('}');
Expand All @@ -5524,7 +5524,7 @@ impl ArriModel for UsersWatchUserResponse {
if _index_ != 0 {
_json_output_.push(',');
}
_json_output_.push_str(format!("\"{}\":", _key_).as_str());
_json_output_.push_str(format!("{}:", serialize_string(_key_)).as_str());
_json_output_.push_str(
serde_json::to_string(_value_)
.unwrap_or("null".to_string())
Expand Down
10 changes: 5 additions & 5 deletions tests/clients/swift/Sources/TestClient.g.swift
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ public struct ObjectWithEveryType: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += "\"\(__value)\""
}
__json += "}"
Expand Down Expand Up @@ -1642,7 +1642,7 @@ if self.record != nil {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
if __value != nil {
__json += "\"\(__value!)\""
} else {
Expand Down Expand Up @@ -2852,7 +2852,7 @@ __numKeys += 1
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += "\"\(__value)\""
}
__json += "}"
Expand Down Expand Up @@ -5509,7 +5509,7 @@ public struct UsersWatchUserResponse: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += __value.toJSONString()
}
__json += "}"
Expand All @@ -5519,7 +5519,7 @@ public struct UsersWatchUserResponse: ArriClientModel {
if __index > 0 {
__json += ","
}
__json += "\"\(__key)\":"
__json += "\(serializeString(input: __key)):"
__json += serializeAny(input: __value)
}
__json += "}"
Expand Down
2 changes: 1 addition & 1 deletion tests/clients/swift/Tests/TestClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ final class TestSwiftClientTests: XCTestCase {
boolean: true,
timestamp: testDate
),
record: Dictionary(dictionaryLiteral: ("A", 1), ("B", 0)),
record: Dictionary(dictionaryLiteral: ("A", 1), ("B", 0), ("\"C\"\t", 0)),
discriminator: ObjectWithEveryTypeDiscriminator.b(
ObjectWithEveryTypeDiscriminatorB(
title: "this is a title",
Expand Down
Loading

0 comments on commit 296de1c

Please sign in to comment.