C# 如何编写一个接受Json的Web服务;多类型属性“;?
上下文:C# 如何编写一个接受Json的Web服务;多类型属性“;?,c#,json,web-services,wcf,asp.net-web-api,C#,Json,Web Services,Wcf,Asp.net Web Api,上下文: Cust有一个发送以下json的服务。他可以轻松地更改该查询的目标,但不能更改查询本身 我必须构建一个接受查询的Web服务,如下面的JSON。 虽然处理Json不会有问题,但我在尝试定义接受类似查询的方法/接口时遇到了问题 这个问题来自Houses>Things:它是一个字符串字典,“objectThing”,其中“objectThing”有一个属性值,可以包含多种类型。 例如: int,“值”:42 字符串,“值”:“Catty” 字符串数组,“值”:[“Book1”、“Book2
Cust有一个发送以下json的服务。他可以轻松地更改该查询的目标,但不能更改查询本身 我必须构建一个接受查询的Web服务,如下面的JSON。 虽然处理Json不会有问题,但我在尝试定义接受类似查询的方法/接口时遇到了问题 这个问题来自Houses>Things:它是一个字符串字典,“
objectThing
”,其中“objectThing
”有一个属性值,可以包含多种类型。例如:
- int,
“值”:42
- 字符串,
“值”:“Catty”
- 字符串数组,
“值”:[“Book1”、“Book2”、“Book3”]
- 对象,对象类型的有限列表
"Value": { "PeopleId": "1234ABCD", "Name": "John" }
"Value": [ { "PeopleId": "1234ABCD", "Name": "John" }, { "PeopleId": "0000AAAA", "Name": "Doe" } ]
- 对象数组,具有有限对象类型列表的数组
"Value": { "PeopleId": "1234ABCD", "Name": "John" }
价值对我来说不是动态的。它在我可以定义的有限类型列表中"Value": [ { "PeopleId": "1234ABCD", "Name": "John" }, { "PeopleId": "0000AAAA", "Name": "Doe" } ]
{
"RootID" : "0123456",
"FooID" : "0123456",
"BarID" : "0123456",
"Houses" :[
{
"OwnerId" : "0123456",
"Date" : 1890895600000,
"Location" : {
"Latitude" : -1,
"Longitude" : -1
},
"Things" :{
"1" :{
"Label": "Books",
"Type" : "List",
"Value": ["Book1", "Book2", "Book3"]
},
"2" :{
"Label": "Cat",
"Type" : "Text",
"Value": "Catty"
},
"3" :{
"Label": "A Number",
"Type" : "Int",
"Value": 42
},
"4" :{
"Label": "Peoples",
"Type" : "People",
"Value": [
{
"PeopleId": "1234ABCD",
"Name": "John"
},
{
"PeopleId": "0000AAAA",
"Name": "Doe"
}
]
}
}
},
{
"OwnerId" : "111111",
"Things" :{}
},
{
"OwnerId" : "000001",
"Things" :{}
}
]
}
以及类定义,如果我要将这个Json反序列化为适当的类型:
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class QueryRoot
{
[JsonProperty("RootID")]
public string RootId { get; set; }
[JsonProperty("FooID")]
public string FooId { get; set; }
[JsonProperty("BarID")]
public string BarId { get; set; }
[JsonProperty("Houses")]
public List<House> Houses { get; set; }
}
public partial class House
{
[JsonProperty("OwnerId")]
public string OwnerId { get; set; }
[JsonProperty("Date", NullValueHandling = NullValueHandling.Ignore)]
public long? Date { get; set; }
[JsonProperty("Location", NullValueHandling = NullValueHandling.Ignore)]
public Location Location { get; set; }
[JsonProperty("Things")]
public Dictionary<string, Thing> Things { get; set; }
}
public partial class Location
{
[JsonProperty("Latitude")]
public long Latitude { get; set; }
[JsonProperty("Longitude")]
public long Longitude { get; set; }
}
public partial class Thing
{
[JsonProperty("Label")]
public string Label { get; set; }
[JsonProperty("Type")]
public string Type { get; set; }
[JsonProperty("Value")]
public ThingValue Value { get; set; }
}
public partial class ValueClass
{
[JsonProperty("PeopleId")]
public string PeopleId { get; set; }
[JsonProperty("Name")]
public string Name { get; set; }
}
public partial struct ValueElement
{
public string String;
public ValueClass ValueClass;
public static implicit operator ValueElement(string String) => new ValueElement { String = String };
public static implicit operator ValueElement(ValueClass ValueClass) => new ValueElement { ValueClass = ValueClass };
}
public partial struct ThingValue
{
public List<ValueElement> AnythingArray;
public long? Integer;
public string String;
public static implicit operator ThingValue(List<ValueElement> AnythingArray) => new ThingValue { AnythingArray = AnythingArray };
public static implicit operator ThingValue(long Integer) => new ThingValue { Integer = Integer };
public static implicit operator ThingValue(string String) => new ThingValue { String = String };
}
public partial class QueryRoot
{
public static QueryRoot FromJson(string json) => JsonConvert.DeserializeObject<QueryRoot>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this QueryRoot self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
ThingValueConverter.Singleton,
ValueElementConverter.Singleton,
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
internal class ThingValueConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(ThingValue) || t == typeof(ThingValue?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.Integer:
var integerValue = serializer.Deserialize<long>(reader);
return new ThingValue { Integer = integerValue };
case JsonToken.String:
case JsonToken.Date:
var stringValue = serializer.Deserialize<string>(reader);
return new ThingValue { String = stringValue };
case JsonToken.StartArray:
var arrayValue = serializer.Deserialize<List<ValueElement>>(reader);
return new ThingValue { AnythingArray = arrayValue };
}
throw new Exception("Cannot unmarshal type ThingValue");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (ThingValue)untypedValue;
if (value.Integer != null)
{
serializer.Serialize(writer, value.Integer.Value);
return;
}
if (value.String != null)
{
serializer.Serialize(writer, value.String);
return;
}
if (value.AnythingArray != null)
{
serializer.Serialize(writer, value.AnythingArray);
return;
}
throw new Exception("Cannot marshal type ThingValue");
}
public static readonly ThingValueConverter Singleton = new ThingValueConverter();
}
internal class ValueElementConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(ValueElement) || t == typeof(ValueElement?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.String:
case JsonToken.Date:
var stringValue = serializer.Deserialize<string>(reader);
return new ValueElement { String = stringValue };
case JsonToken.StartObject:
var objectValue = serializer.Deserialize<ValueClass>(reader);
return new ValueElement { ValueClass = objectValue };
}
throw new Exception("Cannot unmarshal type ValueElement");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (ValueElement)untypedValue;
if (value.String != null)
{
serializer.Serialize(writer, value.String);
return;
}
if (value.ValueClass != null)
{
serializer.Serialize(writer, value.ValueClass);
return;
}
throw new Exception("Cannot marshal type ValueElement");
}
public static readonly ValueElementConverter Singleton = new ValueElementConverter();
}
使用系统;
使用System.Collections.Generic;
利用制度全球化;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Converters;
公共部分类QueryRoot
{
[JsonProperty(“RootID”)]
公共字符串RootId{get;set;}
[JsonProperty(“FooID”)]
公共字符串FooId{get;set;}
[JsonProperty(“BarID”)]
公共字符串BarId{get;set;}
[JsonProperty(“房屋”)]
公共列表屋{get;set;}
}
公屋
{
[JsonProperty(“所有者ID”)]
公共字符串所有者ID{get;set;}
[JsonProperty(“日期”,NullValueHandling=NullValueHandling.Ignore)]
公共长日期{get;set;}
[JsonProperty(“位置”,NullValueHandling=NullValueHandling.Ignore)]
公共位置位置{get;set;}
[JsonProperty(“事物”)]
公共字典事物{get;set;}
}
公共部分类位置
{
[JsonProperty(“纬度”)]
公共长纬度{get;set;}
[JsonProperty(“经度”)]
公共长经度{get;set;}
}
公共部分阶级事物
{
[JsonProperty(“标签”)]
公共字符串标签{get;set;}
[JsonProperty(“类型”)]
公共字符串类型{get;set;}
[JsonProperty(“价值”)]
公共ThingValue{get;set;}
}
公共部分类ValueClass
{
[JsonProperty(“PeopleId”)]
公共字符串PeopleId{get;set;}
[JsonProperty(“名称”)]
公共字符串名称{get;set;}
}
公共部分结构ValueElement
{
公共字符串;
公共价值阶层;
公共静态隐式运算符ValueElement(string)=>new ValueElement{string=string};
公共静态隐式运算符ValueElement(ValueClass ValueClass)=>new ValueElement{ValueClass=ValueClass};
}
公共部分结构ThingValue
{
公开列出任何事情;
公共长整数;
公共字符串;
公共静态隐式运算符ThingValue(List AnythingArray)=>newthingvalue{AnythingArray=AnythingArray};
公共静态隐式运算符ThingValue(长整数)=>newthingvalue{Integer=Integer};
公共静态隐式运算符ThingValue(string string)=>newthingvalue{string=string};
}
公共部分类QueryRoot
{
公共静态QueryRoot FromJson(字符串json)=>JsonConvert.DeserializeObject(json,QuickType.Converter.Settings);
}
公共静态类序列化
{
公共静态字符串ToJson(此QueryRoot self)=>JsonConvert.SerializeObject(self,QuickType.Converter.Settings);
}
内部静态类转换器
{
公共静态只读JsonSerializerSettings设置=新JsonSerializerSettings
{
MetadataPropertyHandling=MetadataPropertyHandling.Ignore,
DateParseHandling=DateParseHandling.None,
转换器=
{
ThingValueConverter.Singleton,
ValueElementConverter.Singleton,
新的IsoDateTimeConverter{DateTimeStyles=DateTimeStyles.AssumeUniversal}
},
};
}
内部类ThingValueConverter:JsonConverter
{
公共覆盖布尔CanConvert(Type t)=>t==typeof(ThingValue)| | t==typeof(ThingValue?);
公共重写对象ReadJson(JsonReader阅读器,类型t,对象existingValue,JsonSerializer序列化程序)
{
开关(reader.TokenType)
{
案例JsonToken.Integer:
var integerValue=序列化程序。反序列化(读取器);
返回新的ThingValue{Integer=integerValue};
case JsonToken.String:
案例JsonToken。日期:
var stringValue=serializer.Deserialize(读取器);
返回新的ThingValue{String=stringValue};
案例JsonToken.StartArray:
var arrayValue=序列化程序。反序列化(读取器);
返回新的ThingValue{AnythingArray=arrayValue};
}
抛出新异常(“无法解组类型ThingValue”);
}
public override void WriteJson(JsonWriter编写器、对象非类型化值、JsonSerializer序列化器)
{
var值=(ThingValue)非类型值;
如果(value.Integer!=null)
{
serializer.Serialize(writer,value.Integer.value);
回来
}
if(value.String!=null)
{
serializer.Serialize(writer,value.String);
回来
}
if(value.AnythingArray!=null)
{
serializer.Serialize(writer、value.AnythingArray);
回来
}
抛出新异常(“无法封送类型ThingValue”);
}
public static readonly ThingValueConverter Singleton=new ThingValueConverter();
}
内部类ValueElementConverter:JsonConverter
{
公共覆盖布尔CanConvert(Type t)=>t==typeof(ValueElement)| | t==typeof(ValueElement?);
公共重写对象ReadJson(JsonReader reader,类型t,对象existingValue,
public class JsonHelper
{
public static string JsonSerializer<T>(T t)
{
var ser = new DataContractJsonSerializer(typeof(T));
var ms = new MemoryStream();
ser.WriteObject(ms, t);
string jsonString = Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
return jsonString;
}
public static T JsonDeserialize<T>(string jsonString)
{
var ser = new DataContractJsonSerializer(typeof(T));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
var obj = (T)ser.ReadObject(ms);
return obj;
}
}