From c88990d9827697b5fd06f89bca88b7906898f09c Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 13:39:03 +0800 Subject: [PATCH 1/9] test case --- .../tsp/arm-stream-style-serialization.tsp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/http-client-java/generator/http-client-generator-test/tsp/arm-stream-style-serialization.tsp b/packages/http-client-java/generator/http-client-generator-test/tsp/arm-stream-style-serialization.tsp index fc109c13e40..d26c8cf9f3d 100644 --- a/packages/http-client-java/generator/http-client-generator-test/tsp/arm-stream-style-serialization.tsp +++ b/packages/http-client-java/generator/http-client-generator-test/tsp/arm-stream-style-serialization.tsp @@ -309,6 +309,9 @@ model Builtin { encoding: Encoded; uuid: Azure.Core.uuid; `unknown`: unknown; + unknownDict: Record; + unknownArray: unknown[]; + unknownDictArray: Record[]; } @encode(DurationKnownEncoding.seconds, float32) From fe6144c521b8b96740c484b6e830c0e7bb1c61fc Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:04:44 +0800 Subject: [PATCH 2/9] regen, code has defect --- .../models/Builtin.java | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java index 4baa115a2f1..f381f8c17e1 100644 --- a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java @@ -122,6 +122,21 @@ public final class Builtin implements JsonSerializable { */ private BinaryData unknown; + /* + * The unknownDict property. + */ + private Map unknownDict; + + /* + * The unknownArray property. + */ + private List unknownArray; + + /* + * The unknownDictArray property. + */ + private List> unknownDictArray; + /** * Creates an instance of Builtin class. */ @@ -508,6 +523,66 @@ public Builtin withUnknown(BinaryData unknown) { return this; } + /** + * Get the unknownDict property: The unknownDict property. + * + * @return the unknownDict value. + */ + public Map unknownDict() { + return this.unknownDict; + } + + /** + * Set the unknownDict property: The unknownDict property. + * + * @param unknownDict the unknownDict value to set. + * @return the Builtin object itself. + */ + public Builtin withUnknownDict(Map unknownDict) { + this.unknownDict = unknownDict; + return this; + } + + /** + * Get the unknownArray property: The unknownArray property. + * + * @return the unknownArray value. + */ + public List unknownArray() { + return this.unknownArray; + } + + /** + * Set the unknownArray property: The unknownArray property. + * + * @param unknownArray the unknownArray value to set. + * @return the Builtin object itself. + */ + public Builtin withUnknownArray(List unknownArray) { + this.unknownArray = unknownArray; + return this; + } + + /** + * Get the unknownDictArray property: The unknownDictArray property. + * + * @return the unknownDictArray value. + */ + public List> unknownDictArray() { + return this.unknownDictArray; + } + + /** + * Set the unknownDictArray property: The unknownDictArray property. + * + * @param unknownDictArray the unknownDictArray value to set. + * @return the Builtin object itself. + */ + public Builtin withUnknownDictArray(List> unknownDictArray) { + this.unknownDictArray = unknownDictArray; + return this; + } + /** * Validates the instance. * @@ -565,6 +640,18 @@ public void validate() { throw LOGGER.atError() .log(new IllegalArgumentException("Missing required property unknown in model Builtin")); } + if (unknownDict() == null) { + throw LOGGER.atError() + .log(new IllegalArgumentException("Missing required property unknownDict in model Builtin")); + } + if (unknownArray() == null) { + throw LOGGER.atError() + .log(new IllegalArgumentException("Missing required property unknownArray in model Builtin")); + } + if (unknownDictArray() == null) { + throw LOGGER.atError() + .log(new IllegalArgumentException("Missing required property unknownDictArray in model Builtin")); + } } private static final ClientLogger LOGGER = new ClientLogger(Builtin.class); @@ -597,6 +684,13 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStringField("uuid", this.uuid); jsonWriter.writeFieldName("unknown"); this.unknown.writeTo(jsonWriter); + jsonWriter.writeMapField("unknownDict", this.unknownDict, + (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); + jsonWriter.writeArrayField("unknownArray", this.unknownArray, + (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); + jsonWriter.writeArrayField("unknownDictArray", this.unknownDictArray, (writer, element) -> writer.writeMap( + element, + (writer1, element1) -> writer1.writeUntyped(element1 == null ? null : element1.toObject(Object.class)))); return jsonWriter.writeEndObject(); } @@ -663,6 +757,19 @@ public static Builtin fromJson(JsonReader jsonReader) throws IOException { } else if ("unknown".equals(fieldName)) { deserializedBuiltin.unknown = reader.getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped())); + } else if ("unknownDict".equals(fieldName)) { + Map unknownDict = reader.readMap(reader1 -> reader1 + .getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + deserializedBuiltin.unknownDict = unknownDict; + } else if ("unknownArray".equals(fieldName)) { + List unknownArray = reader.readArray(reader1 -> reader1 + .getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + deserializedBuiltin.unknownArray = unknownArray; + } else if ("unknownDictArray".equals(fieldName)) { + List> unknownDictArray + = reader.readArray(reader1 -> reader1.readMap(reader2 -> reader2 + .getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped())))); + deserializedBuiltin.unknownDictArray = unknownDictArray; } else { reader.skipChildren(); } From 806b75a8756f498bd6ba804ad301edf7ef581e56 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:23:36 +0800 Subject: [PATCH 3/9] add test --- .../StreamStyleSerializationTests.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java index af56b1cdd2c..e956f461593 100644 --- a/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java +++ b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java @@ -11,6 +11,9 @@ import com.azure.core.util.serializer.SerializerAdapter; import com.azure.core.util.serializer.SerializerEncoding; import com.azure.json.JsonProviders; +import com.azure.json.JsonReader; +import com.azure.json.JsonSerializable; +import com.azure.json.JsonToken; import com.azure.json.JsonWriter; import java.io.IOException; import java.io.StringWriter; @@ -107,6 +110,73 @@ public void testPropertyWithNullValue() { Assertions.assertEquals("input", jsonDict.get("input")); } + public final static class TestBinary implements JsonSerializable { + private Map unknownDict; + + public Map unknownDict() { + return this.unknownDict; + } + + public TestBinary() { + } + + public TestBinary withUnknownDict(Map unknownDict) { + this.unknownDict = unknownDict; + return this; + } + + @Override + public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { + jsonWriter.writeStartObject(); + jsonWriter.writeMapField("unknownDict", this.unknownDict, (writer, element) -> { + if (element == null) { + writer.writeNull(); + } else { + element.writeTo(writer); + } + }); + return jsonWriter.writeEndObject(); + } + + public static TestBinary fromJson(JsonReader jsonReader) throws IOException { + return jsonReader.readObject(reader -> { + TestBinary deserializedTestBinary = new TestBinary(); + while (reader.nextToken() != JsonToken.END_OBJECT) { + String fieldName = reader.getFieldName(); + reader.nextToken(); + + if ("unknownDict".equals(fieldName)) { + Map unknownDict = reader.readMap(reader1 -> reader1 + .getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + deserializedTestBinary.unknownDict = unknownDict; + } else { + reader.skipChildren(); + } + } + + return deserializedTestBinary; + }); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testBinaryDataInContainer() { + // use a simple class + TestBinary model = new TestBinary().withUnknownDict( + Map.of("string", BinaryData.fromString("value"), "object", BinaryData.fromString("{\"k\", \"v\"}"))); + + com.azure.core.util.BinaryData binaryData = BinaryData.fromObject(model); + String jsonString = binaryData.toString(); + Map jsonMap = BinaryData.fromString(jsonString).toObject(Map.class); + Assertions.assertTrue(jsonMap.containsKey("unknownDict")); + Map unknownDict = (Map) jsonMap.get("unknownDict"); + Assertions.assertEquals("value", unknownDict.get("string")); + Assertions.assertEquals("{\"k\", \"v\"}", unknownDict.get("object")); + + model = binaryData.toObject(TestBinary.class); + } + @Test public void ensureInstantMaxValue() { // ensure Integer.MAX_VALUE doesn't exceeds Instant.MAX From 5065d2690b88b8481aa45b8c51a2caf7090d7bb5 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:27:43 +0800 Subject: [PATCH 4/9] special handling for BinaryData --- .../core/template/StreamSerializationModelTemplate.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/StreamSerializationModelTemplate.java b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/StreamSerializationModelTemplate.java index c8656983965..b964ecf4676 100644 --- a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/StreamSerializationModelTemplate.java +++ b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/StreamSerializationModelTemplate.java @@ -879,7 +879,11 @@ private static void serializeJsonContainerProperty(JavaBlock methodBlock, String } methodBlock.indent(() -> { - if (valueSerializationMethod != null) { + if (elementType == ClassType.BINARY_DATA) { + // Special handling for BinaryData + methodBlock.line("{ if (%1$s == null) { %2$s.writeNull(); } else { %1$s.writeTo(%2$s); } }", + elementName, lambdaWriterName); + } else if (valueSerializationMethod != null) { if (isJsonMergePatch && containerType instanceof MapType) { methodBlock.block("", codeBlock -> codeBlock.ifBlock(elementName + "!= null", ifBlock -> { if (elementType instanceof ClassType && ((ClassType) elementType).isSwaggerType()) { @@ -908,8 +912,6 @@ private static void serializeJsonContainerProperty(JavaBlock methodBlock, String serializeJsonContainerProperty(methodBlock, "writeMap", elementType, ((MapType) elementType).getValueType(), serializedName, propertyValueGetter, depth + 1, isJsonMergePatch); - } else if (elementType == ClassType.BINARY_DATA) { - methodBlock.line(elementName + ".writeTo(" + lambdaWriterName + ")"); } else { throw new RuntimeException("Unknown value type " + elementType + " in " + containerType + " serialization. Need to add support for it."); From 56714b472aa8b4416c01b4f621a9403a76f847f8 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:35:02 +0800 Subject: [PATCH 5/9] regen --- .../models/Builtin.java | 29 ++++++++++++++----- .../type/union/models/MixedTypesCases.java | 9 ++++-- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java index f381f8c17e1..f450c4a17fc 100644 --- a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/armstreamstyleserialization/models/Builtin.java @@ -684,13 +684,28 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStringField("uuid", this.uuid); jsonWriter.writeFieldName("unknown"); this.unknown.writeTo(jsonWriter); - jsonWriter.writeMapField("unknownDict", this.unknownDict, - (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); - jsonWriter.writeArrayField("unknownArray", this.unknownArray, - (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); - jsonWriter.writeArrayField("unknownDictArray", this.unknownDictArray, (writer, element) -> writer.writeMap( - element, - (writer1, element1) -> writer1.writeUntyped(element1 == null ? null : element1.toObject(Object.class)))); + jsonWriter.writeMapField("unknownDict", this.unknownDict, (writer, element) -> { + if (element == null) { + writer.writeNull(); + } else { + element.writeTo(writer); + } + }); + jsonWriter.writeArrayField("unknownArray", this.unknownArray, (writer, element) -> { + if (element == null) { + writer.writeNull(); + } else { + element.writeTo(writer); + } + }); + jsonWriter.writeArrayField("unknownDictArray", this.unknownDictArray, + (writer, element) -> writer.writeMap(element, (writer1, element1) -> { + if (element1 == null) { + writer1.writeNull(); + } else { + element1.writeTo(writer1); + } + })); return jsonWriter.writeEndObject(); } diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/type/union/models/MixedTypesCases.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/type/union/models/MixedTypesCases.java index a1432230f8b..8adfc9a891b 100644 --- a/packages/http-client-java/generator/http-client-generator-test/src/main/java/type/union/models/MixedTypesCases.java +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/type/union/models/MixedTypesCases.java @@ -133,8 +133,13 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { this.intProperty.writeTo(jsonWriter); jsonWriter.writeFieldName("boolean"); this.booleanProperty.writeTo(jsonWriter); - jsonWriter.writeArrayField("array", this.array, - (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); + jsonWriter.writeArrayField("array", this.array, (writer, element) -> { + if (element == null) { + writer.writeNull(); + } else { + element.writeTo(writer); + } + }); return jsonWriter.writeEndObject(); } From d734a8a3754e4452ed8fdbfcd9b0dcd5f6306d35 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:44:57 +0800 Subject: [PATCH 6/9] regen --- .../src/main/java/type/union/MixedTypesCases.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/http-client-java/generator/http-client-generator-clientcore-test/src/main/java/type/union/MixedTypesCases.java b/packages/http-client-java/generator/http-client-generator-clientcore-test/src/main/java/type/union/MixedTypesCases.java index 7f29429d680..ab22bd28590 100644 --- a/packages/http-client-java/generator/http-client-generator-clientcore-test/src/main/java/type/union/MixedTypesCases.java +++ b/packages/http-client-java/generator/http-client-generator-clientcore-test/src/main/java/type/union/MixedTypesCases.java @@ -129,8 +129,13 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { this.intProperty.writeTo(jsonWriter); jsonWriter.writeFieldName("boolean"); this.booleanProperty.writeTo(jsonWriter); - jsonWriter.writeArrayField("array", this.array, - (writer, element) -> writer.writeUntyped(element == null ? null : element.toObject(Object.class))); + jsonWriter.writeArrayField("array", this.array, (writer, element) -> { + if (element == null) { + writer.writeNull(); + } else { + element.writeTo(writer); + } + }); return jsonWriter.writeEndObject(); } From f2e754ba4ceb74e97e8269cce877df48298afe3c Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 14:58:08 +0800 Subject: [PATCH 7/9] escape the mock string data for BinaryData and Object --- .../http/client/generator/core/util/ModelTestCaseUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/util/ModelTestCaseUtil.java b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/util/ModelTestCaseUtil.java index f38954434f8..cc4cbe0e432 100644 --- a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/util/ModelTestCaseUtil.java +++ b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/util/ModelTestCaseUtil.java @@ -129,7 +129,7 @@ public static Object jsonFromType(int depth, IType type) { return "http://example.org/" + URLEncoder.encode(randomString(), StandardCharsets.UTF_8); } else if (type == ClassType.OBJECT || type == ClassType.BINARY_DATA) { // unknown type, use a simple string - return "data" + randomString(); + return ClassType.STRING.defaultValueExpression("data" + randomString()); } else if (type instanceof EnumType) { IType elementType = ((EnumType) type).getElementType(); List values From b8d34c9df0809ee80396d35cf78218f98014cb93 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 15:08:38 +0800 Subject: [PATCH 8/9] changelog --- ...g-fix-serialization-dict-of-unknown-2026-1-9-15-8-29.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/http-client-java_bug-fix-serialization-dict-of-unknown-2026-1-9-15-8-29.md diff --git a/.chronus/changes/http-client-java_bug-fix-serialization-dict-of-unknown-2026-1-9-15-8-29.md b/.chronus/changes/http-client-java_bug-fix-serialization-dict-of-unknown-2026-1-9-15-8-29.md new file mode 100644 index 00000000000..29fba344fd2 --- /dev/null +++ b/.chronus/changes/http-client-java_bug-fix-serialization-dict-of-unknown-2026-1-9-15-8-29.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-java" +--- + +Fix mock data for BinaryData. \ No newline at end of file From 9536019cf6b133a2a24a86394e0ea2887c0b1132 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 9 Feb 2026 15:20:50 +0800 Subject: [PATCH 9/9] fix test --- .../StreamStyleSerializationTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java index e956f461593..8521d76f970 100644 --- a/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java +++ b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/armstreamstyleserialization/StreamStyleSerializationTests.java @@ -164,14 +164,14 @@ public static TestBinary fromJson(JsonReader jsonReader) throws IOException { public void testBinaryDataInContainer() { // use a simple class TestBinary model = new TestBinary().withUnknownDict( - Map.of("string", BinaryData.fromString("value"), "object", BinaryData.fromString("{\"k\", \"v\"}"))); + Map.of("string", BinaryData.fromString("\"value\""), "object", BinaryData.fromString("{\"k\", \"v\"}"))); com.azure.core.util.BinaryData binaryData = BinaryData.fromObject(model); String jsonString = binaryData.toString(); Map jsonMap = BinaryData.fromString(jsonString).toObject(Map.class); Assertions.assertTrue(jsonMap.containsKey("unknownDict")); Map unknownDict = (Map) jsonMap.get("unknownDict"); - Assertions.assertEquals("value", unknownDict.get("string")); + Assertions.assertEquals("\"value\"", unknownDict.get("string")); Assertions.assertEquals("{\"k\", \"v\"}", unknownDict.get("object")); model = binaryData.toObject(TestBinary.class);