Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/http-client-java/emitter/src/code-model-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import { fail } from "assert";
import pkg from "lodash";
import {
Client as CodeModelClient,
EncodedProperty,
EncodedSchema,
PageableContinuationToken,
Serializable,
Expand Down Expand Up @@ -2865,6 +2866,18 @@ export class CodeModelBuilder {
serializedName: getPropertySerializedName(modelProperty),
extensions: extensions,
});
if (modelProperty.encode) {
if (schema instanceof ArraySchema) {
const elementSchema = schema.elementType;
if (!(elementSchema instanceof StringSchema)) {
reportDiagnostic(this.program, {
code: "non-string-array-encoding-element-notsupported",
target: modelProperty.__raw ?? NoTarget,
});
}
}
(codeModelProperty as EncodedProperty).arrayEncoding = modelProperty.encode;
}

// xml
if (modelProperty.serializationOptions.xml) {
Expand Down
9 changes: 9 additions & 0 deletions packages/http-client-java/emitter/src/common/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Security,
} from "@autorest/codemodel";
import { DeepPartial } from "@azure-tools/codegen";
import { ArrayKnownEncoding } from "@azure-tools/typespec-client-generator-core";
import { XmlSerializationFormat } from "./formats/xml.js";

export interface Client extends Aspect {
Expand Down Expand Up @@ -103,6 +104,14 @@ export interface EncodedSchema {
encode?: string;
}

export interface EncodedProperty {
/**
* The encoding of array items.
* The type for SDK would "SdkArrayType" with a "valueType", the type on wire be "string".
*/
arrayEncoding?: ArrayKnownEncoding;
}

export class PageableContinuationToken {
/**
* The parameter of the operation as continuationToken in API request.
Expand Down
6 changes: 6 additions & 0 deletions packages/http-client-java/emitter/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ export const $lib = createTypeSpecLibrary({
default: paramMessage`Constant header '${"headerName"}' is removed from response headers.`,
},
},
"non-string-array-encoding-element-notsupported": {
severity: "error",
messages: {
default: "Element of type other than 'string' is not supported for 'ArrayEncoding'.",
},
},
},
emitter: {
options: EmitterOptionsSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@typespec/http-client-java-tests": "file:"
},
"overrides": {
"@typespec/compiler": "1.7.0",
"@typespec/compiler": "1.7.1",
"@typespec/http": "1.7.0",
"@typespec/rest": "0.77.0",
"@typespec/versioning": "0.77.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import io.clientcore.core.serialization.json.JsonToken;
import io.clientcore.core.serialization.json.JsonWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
* The CommaDelimitedArrayProperty model.
Expand Down Expand Up @@ -47,7 +50,10 @@ public List<String> getValue() {
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeArrayField("value", this.value, (writer, element) -> writer.writeString(element));
if (this.value != null) {
jsonWriter.writeStringField("value",
this.value.stream().map(element -> element == null ? "" : element).collect(Collectors.joining(",")));
Comment on lines +54 to +55
Copy link
Contributor Author

@weidongxu-microsoft weidongxu-microsoft Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both null and "" would map to same encoded string.

On the other direction, currently we map e.g. "," to ["", ""] for string element.
For other type that extend string, we may choose differently (or even break this behavior on string type too), e.g. "," on utcDateTime/uuid can only be [null, null]

Just hope service knows what it does on these...

}
return jsonWriter.writeEndObject();
}

Expand All @@ -69,7 +75,12 @@ public static CommaDelimitedArrayProperty fromJson(JsonReader jsonReader) throws
reader.nextToken();

if ("value".equals(fieldName)) {
value = reader.readArray(reader1 -> reader1.getString());
String valueEncodedAsString = reader.getString();
value = valueEncodedAsString == null
? null
: valueEncodedAsString.isEmpty()
? new LinkedList<>()
: new LinkedList<>(Arrays.asList(valueEncodedAsString.split(",", -1)));
} else {
reader.skipChildren();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import io.clientcore.core.serialization.json.JsonToken;
import io.clientcore.core.serialization.json.JsonWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
* The NewlineDelimitedArrayProperty model.
Expand Down Expand Up @@ -47,7 +50,10 @@ public List<String> getValue() {
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeArrayField("value", this.value, (writer, element) -> writer.writeString(element));
if (this.value != null) {
jsonWriter.writeStringField("value",
this.value.stream().map(element -> element == null ? "" : element).collect(Collectors.joining("\n")));
}
return jsonWriter.writeEndObject();
}

Expand All @@ -69,7 +75,12 @@ public static NewlineDelimitedArrayProperty fromJson(JsonReader jsonReader) thro
reader.nextToken();

if ("value".equals(fieldName)) {
value = reader.readArray(reader1 -> reader1.getString());
String valueEncodedAsString = reader.getString();
value = valueEncodedAsString == null
? null
: valueEncodedAsString.isEmpty()
? new LinkedList<>()
: new LinkedList<>(Arrays.asList(valueEncodedAsString.split("\n", -1)));
} else {
reader.skipChildren();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import io.clientcore.core.serialization.json.JsonToken;
import io.clientcore.core.serialization.json.JsonWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
* The PipeDelimitedArrayProperty model.
Expand Down Expand Up @@ -47,7 +50,10 @@ public List<String> getValue() {
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeArrayField("value", this.value, (writer, element) -> writer.writeString(element));
if (this.value != null) {
jsonWriter.writeStringField("value",
this.value.stream().map(element -> element == null ? "" : element).collect(Collectors.joining("|")));
}
return jsonWriter.writeEndObject();
}

Expand All @@ -69,7 +75,12 @@ public static PipeDelimitedArrayProperty fromJson(JsonReader jsonReader) throws
reader.nextToken();

if ("value".equals(fieldName)) {
value = reader.readArray(reader1 -> reader1.getString());
String valueEncodedAsString = reader.getString();
value = valueEncodedAsString == null
? null
: valueEncodedAsString.isEmpty()
? new LinkedList<>()
: new LinkedList<>(Arrays.asList(valueEncodedAsString.split("\\|", -1)));
} else {
reader.skipChildren();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import io.clientcore.core.serialization.json.JsonToken;
import io.clientcore.core.serialization.json.JsonWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
* The SpaceDelimitedArrayProperty model.
Expand Down Expand Up @@ -47,7 +50,10 @@ public List<String> getValue() {
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeArrayField("value", this.value, (writer, element) -> writer.writeString(element));
if (this.value != null) {
jsonWriter.writeStringField("value",
this.value.stream().map(element -> element == null ? "" : element).collect(Collectors.joining(" ")));
}
return jsonWriter.writeEndObject();
}

Expand All @@ -69,7 +75,12 @@ public static SpaceDelimitedArrayProperty fromJson(JsonReader jsonReader) throws
reader.nextToken();

if ("value".equals(fieldName)) {
value = reader.readArray(reader1 -> reader1.getString());
String valueEncodedAsString = reader.getString();
value = valueEncodedAsString == null
? null
: valueEncodedAsString.isEmpty()
? new LinkedList<>()
: new LinkedList<>(Arrays.asList(valueEncodedAsString.split(" ", -1)));
} else {
reader.skipChildren();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package encode.array;

import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public final class EncodeArrayTests {

private static final List<String> COLORS = List.of("blue", "red", "green");

private final ArrayClient client = new ArrayClientBuilder().buildArrayClient();

@Test
public void commaDelimitedProperty() {
CommaDelimitedArrayProperty response = client.commaDelimited(new CommaDelimitedArrayProperty(COLORS));
Assertions.assertEquals(COLORS, response.getValue());
}

@Test
public void spaceDelimitedProperty() {
SpaceDelimitedArrayProperty response = client.spaceDelimited(new SpaceDelimitedArrayProperty(COLORS));
Assertions.assertEquals(COLORS, response.getValue());
}

@Test
public void pipeDelimitedProperty() {
PipeDelimitedArrayProperty response = client.pipeDelimited(new PipeDelimitedArrayProperty(COLORS));
Assertions.assertEquals(COLORS, response.getValue());
}

@Test
public void newlineDelimitedProperty() {
NewlineDelimitedArrayProperty response = client.newlineDelimited(new NewlineDelimitedArrayProperty(COLORS));
Assertions.assertEquals(COLORS, response.getValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class Property extends Value {
private String summary;
// TypeSpec only
private SerializationFormats serialization;
private String arrayEncoding;
// internal use, not from modelerfour
private ObjectSchema parentSchema;

Expand Down Expand Up @@ -161,6 +162,24 @@ public void setSerialization(SerializationFormats serialization) {
this.serialization = serialization;
}

/**
* Gets the array encoding style of this property.
*
* @return The array encoding style of this property.
*/
public String getArrayEncoding() {
return arrayEncoding;
}

/**
* Sets the array encoding style of this property.
*
* @param arrayEncoding The array encoding style of this property.
*/
public void setArrayEncoding(String arrayEncoding) {
this.arrayEncoding = arrayEncoding;
}

@Override
public String getSummary() {
return summary;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.Schema;
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.XmlSerializationFormat;
import com.microsoft.typespec.http.client.generator.core.extension.plugin.JavaSettings;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ArrayEncoding;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClientModelProperty;
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.EnumType;
Expand Down Expand Up @@ -242,6 +243,11 @@ public ClientModelProperty map(Property property, boolean mutableAsOptional) {
builder.defaultValue(autoRestPropertyDefaultValueExpression);
}

// array encoding
if (property.getArrayEncoding() != null) {
builder.arrayEncoding(ArrayEncoding.fromValue(property.getArrayEncoding()));
}

return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.typespec.http.client.generator.core.model.clientmodel;

/**
* Known array encoding strategies supported by the generator.
*/
public enum ArrayEncoding {
PIPE_DELIMITED("pipeDelimited", "|", "\\\\|"),
SPACE_DELIMITED("spaceDelimited", " "),
COMMA_DELIMITED("commaDelimited", ","),
NEWLINE_DELIMITED("newlineDelimited", "\\n");

private final String value;
private final String delimiter;
private final String escapedDelimiter;

ArrayEncoding(String value, String delimiter) {
this.value = value;
this.delimiter = delimiter;
this.escapedDelimiter = delimiter;
}

ArrayEncoding(String value, String delimiter, String escapedDelimiter) {
this.value = value;
this.delimiter = delimiter;
this.escapedDelimiter = escapedDelimiter;
}

public String value() {
return this.value;
}

public String getDelimiter() {
return this.delimiter;
}

public String getEscapedDelimiter() {
return escapedDelimiter;
}

@Override
public String toString() {
return this.value();
}

public static ArrayEncoding fromValue(String value) {
if (value == null) {
return null;
}

for (ArrayEncoding v : values()) {
if (v.value().equalsIgnoreCase(value)) {
return v;
}
}
return null;
}
}
Loading
Loading