Use transformation's target types in propertiesIf we don't, we end up with the non-transformed source types, suchas "string" for enums, or "object" for unions.

This commit is contained in:
Mark Probst 2018-06-10 09:48:48 -07:00
Родитель 7f4d2bcb2b
Коммит cf951744c1
3 изменённых файлов: 60 добавлений и 34 удалений

Просмотреть файл

@ -253,7 +253,7 @@ export class CSharpRenderer extends ConvenienceRenderer {
enumType => this.nameForNamedType(enumType),
unionType => {
const nullable = nullableFromUnion(unionType);
if (nullable !== null) return this.nullableCSType(nullable);
if (nullable !== null) return this.nullableCSType(nullable, noFollow);
return this.nameForNamedType(unionType);
},
{
@ -262,9 +262,13 @@ export class CSharpRenderer extends ConvenienceRenderer {
);
}
protected nullableCSType(t: Type, withIssues: boolean = false): Sourcelike {
protected nullableCSType(
t: Type,
follow: (t: Type) => Type = followTargetType,
withIssues: boolean = false
): Sourcelike {
t = followTargetType(t);
const csType = this.csType(t, noFollow, withIssues);
const csType = this.csType(t, follow, withIssues);
if (isValueType(t)) {
return [csType, "?"];
} else {
@ -311,8 +315,10 @@ export class CSharpRenderer extends ConvenienceRenderer {
}
protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike {
const t = followTargetType(property.type);
const csType = property.isOptional ? this.nullableCSType(t, true) : this.csType(t, noFollow, true);
const t = property.type;
const csType = property.isOptional
? this.nullableCSType(t, followTargetType, true)
: this.csType(t, followTargetType, true);
return ["public ", csType, " ", name, " { get; set; }"];
}
@ -930,6 +936,9 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
const memberName = this.nameForUnionMember(xfer.sourceType, xfer.memberType);
member = [variable, ".", memberName];
test = [member, " != null"];
if (isValueType(xfer.memberType)) {
member = [member, ".Value"];
}
}
this.emitLine("if (", test, ")");
this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType));
@ -945,7 +954,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))");
this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType));
} else if (xfer instanceof StringifyDateTimeTransformer) {
return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType);
return this.emitConsume(
[variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'],
xfer.consumer,
targetType
);
} else if (xfer instanceof StringProducerTransformer) {
const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result);
return this.emitConsume(value, xfer.consumer, targetType);
@ -979,11 +992,14 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
this.emitCanConvert(["t == typeof(", csType, ") || t == typeof(", csType, "?)"]);
this.ensureBlankLine();
this.emitReadJson(() => {
const allHandled = this.emitDecodeTransformer(xfer, targetType);
// FIXME: It's unsatisfying that we need this. The reason is that we not
// only match T, but also T?. If we didn't, then the T in T? would not be
// deserialized with our converter but with the default one.
// deserialized with our converter but with the default one. Can we check
// whether the type is a nullable?
// FIXMEL: This could duplicate one of the cases handled above in
// `emitDecodeTransformer`.
this.emitLine("if (reader.TokenType == JsonToken.Null) return null;");
const allHandled = this.emitDecodeTransformer(xfer, targetType);
if (!allHandled) {
this.emitThrow(['"Cannot unmarshal type ', csType, '"']);
}

Просмотреть файл

@ -0,0 +1,4 @@
{
"gve": "good",
"otherArr": ["foo", "bar", "if"]
}

Просмотреть файл

@ -1,29 +1,35 @@
{
"type": "object",
"properties": {
"lvc": {
"enum": ["lawful", "neutral", "chaotic"]
},
"gve": {
"type": "string",
"enum": ["good", "neutral", "evil"]
},
"arr": {
"type": "array",
"items": {
"oneOf": [
{
"enum": ["foo", "bar", "if"]
},
{
"type": "integer"
}
]
}
},
"for": {
"type": "string"
}
"type": "object",
"properties": {
"lvc": {
"enum": ["lawful", "neutral", "chaotic"]
},
"required": ["gve"]
"gve": {
"type": "string",
"enum": ["good", "neutral", "evil"]
},
"arr": {
"type": "array",
"items": {
"oneOf": [
{
"enum": ["foo", "bar", "if"]
},
{
"type": "integer"
}
]
}
},
"otherArr": {
"type": "array",
"items": {
"enum": ["foo", "bar", "if"]
}
},
"for": {
"type": "string"
}
},
"required": ["gve"]
}