问题
I need to read an JSON object from TypeScript, which has a variable names prop
which of two types, either Identifier
or Expression
to C#. TypeScript can have a variable with multiple types (with its union type feature), e.g., prop
is defined as
var property:Identifier | Expression
I am reading the JSON object string from C# with JsonConvert.DeserializeObject
, e.g.,
Object facebookFriends = new JavaScriptSerializer().Deserialize<Object>(JSON_Object);
How should I declare a variable of two types in C#? Or should I just use object
(i.e., declare as Object property
)?
回答1:
If the property can have either of these two formats:
{ "prop": "identifier" }
{ "prop": { "complex": "object" } }
ie. either a simple string or a more complex object you can solve this by using dynamic
to accept the parsed prop
value, and extra properties to return either the identifier or the complex object. Here is a LINQPad program that demonstrates:
void Main()
{
var jsonStrings = new[]
{
"{ \"prop\": \"identifier\" }",
"{ \"prop\": { \"complex\": \"object\" } }"
};
jsonStrings.Select(json => JsonConvert.DeserializeObject<Test>(json)).Dump();
}
public class Test
{
public Test()
{
_Complex = new Lazy<Complex>(GetComplex);
}
[JsonProperty("prop")]
public dynamic prop { get; set; }
[JsonIgnore]
public string Identifier => prop as string;
private readonly Lazy<Complex> _Complex;
[JsonIgnore]
public Complex Complex => _Complex.Value;
private Complex GetComplex()
{
if (!(prop is JObject))
return null;
return ((JObject)prop).ToObject<Complex>();
}
}
public class Complex
{
public string complex { get; set; }
}
Output:
A different approach would be to create your own types to handle the multiple outputs and again use a secondary property to evaluate what you actually got from the json:
void Main()
{
var jsonStrings = new[]
{
"{ \"prop\": \"identifier\" }",
"{ \"prop\": { \"complex\": \"object\" } }"
};
jsonStrings.Select(json => JsonConvert.DeserializeObject<Test>(json)).Dump();
}
public class Test
{
[JsonProperty("prop")]
public dynamic prop { get; set; }
[JsonIgnore]
public PropertyValue Property
{
get
{
if (prop is string)
return new IdentifierProperty(prop as string);
return new ExpressionProperty(((JObject)prop).ToObject<Expression>());
}
}
}
public abstract class PropertyValue
{
}
public class IdentifierProperty : PropertyValue
{
public IdentifierProperty(string identifier)
{
Identifier = identifier;
}
public string Identifier { get; }
public override string ToString() => Identifier;
}
public class ExpressionProperty : PropertyValue
{
public ExpressionProperty(Expression expression)
{
Expression = expression;
}
public Expression Expression { get; }
public override string ToString() => Expression.ToString();
}
public class Expression
{
public string complex { get; set; }
public override string ToString() => $"complex: {complex}";
}
Output:
来源:https://stackoverflow.com/questions/34395609/a-variable-of-two-types