我正在编写一个实用程序,该实用程序读取文本文件(json)并动态构造一个json对象并将其发送到REST API。为了实现这一点,我希望我的序列化json对象(我在C#中使用Json.Net创建了该对象)也保留每个字段的类型信息及其值。
例如,我希望我的json文件采用类似格式:
{
"fieldString": {
"type": "string",
"value": "my custom string data"
},
"fieldTimeStamp": {
"type": "date",
"value": "2018-12-10T08:25:55.150Z"
},
"fieldNumber": {
"type": "number",
"value": 999999.999
},
"fieldGeopoint": {
"type": "geopoint",
"value": {
"_latitude": 0.0,
"_longitude": 0.0
}
},
}
感谢社区成员提出的问题,这是其他信息,希望对您有所帮助...
我的实用程序将是数据上传实用程序,它将独立于任何应用程序读取数据。这将从json文件中读取数据,并构造一个正确的对象以调用REST API(任意)。例如GeoPoint对象,它不是原始数据类型,并且不同的语言可能具有与此对象关联的不同名称和属性。
创建json文件的工具将负责提供键入的信息以及每个对象的字段值。我的数据上传实用程序将决定如何解释将GeoPoint传递给其他API的方法,例如,在Azure CosmosDB中,geopoint称为“ Point”,而在好世界中,geopoint称为“ GeoPoint”,其他人可能会有不同相同基础信息的名称。或者例如,有些可以区分“ int”和“ float”,而另一些则不能。
答案 0 :(得分:0)
这已经是JSON.Net序列化程序中内置的功能:
How to serialize object to json with type info using Newtonsoft.Json?
我相信您可以利用这一点:区别实际上是原始类型和对象类型之间的区别。如果您有一个object属性,则它是原始类型(也许不是)将被支持。因此,您需要为每种原始类型创建一个单独的类。您将创建自己的String对象,Date对象,Number对象等等(在C#端)。
此外,您可以直接使用JsonWriter / JsonReader。它们不太难使用,并且将为您提供对协议的最佳控制。直接代码将使其易于调试,并且还会产生性能非常好的副作用。 (通常,JSON.net使用反射和/或运行时编译的帮助程序类)
答案 1 :(得分:0)
尽管我按照@ZoharPeled的建议使用Json Schema路径。
但是正如@Todd所建议的那样,我创建了以下解决方案,该解决方案在序列化对象时保留字段的对象类型信息。我将其放在此处仅供参考,以防万一有人要引用它。
class TypeInfoConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var converters = serializer.Converters.Where(x => !(x is TypeInfoConverter)).ToArray();
JToken jToken = JToken.FromObject(value);
JObject jObject;
switch (jToken.Type)
{
case JTokenType.Object:
case JTokenType.Array:
case JTokenType.Bytes:
case JTokenType.Date:
jObject = JObject.FromObject(new Converter(value));
jObject.WriteTo(writer, converters);
break;
default:
//jObject = JObject.FromObject(new Converter(value));
//jObject.WriteTo(writer);
jToken.WriteTo(writer);
break;
}
}
class Converter
{
public Dictionary<string, object> _attr = new Dictionary<string, object>();
public object value;
public Converter(object value)
{
this.value = value;
addAttributes();
}
private void addAttributes()
{
Type t = value.GetType();
_attr["type"] = t.Name;
if (t.IsGenericType
&& (value is IList || value is IDictionary))
{
collectionAttributes(value, _attr, t);
}
else if (t.IsEnum)
{
_attr["type"] = "enum";
_attr["class"] = t.Name;
//attributes["meaning"] = value.ToString();
}
}
private void collectionAttributes(object value, Dictionary<string, object> attr, Type type)
{
Dictionary<string, object> o = new Dictionary<string, object>();
if (value is IDictionary && value.GetType().IsGenericType)
{
attr["type"] = "map";
attr["key"] = type.GetGenericArguments()[0].Name;
if(type.GetGenericArguments()[1].IsGenericType == true)
{
collectionAttributes(((IDictionary)value).Values, o, type.GetGenericArguments()[1]);
attr["value"] = o;
}
else
{
attr["value"] = type.GetGenericArguments()[1].Name;
}
}
else if (value is ICollection && type.IsGenericType)
{
attr["type"] = "array";
if (type.GetGenericArguments()[0].IsGenericType == true)
{
collectionAttributes(value, o, type.GetGenericArguments()[0]);
attr["value"] = o;
}
else
{
attr["of"] = type.GetGenericArguments()[0].Name;
}
}
}
}
用法
class TrialObject
{
[JsonConverter(typeof(TypeInfoConverter))]
public String szObject = "trial string";
[JsonConverter(typeof(TypeInfoConverter))]
public Double doubleObject = 999999999.999;
[JsonConverter(typeof(TypeInfoConverter))]
public Boolean boolObject = true;
[JsonConverter(typeof(TypeInfoConverter))]
public DateTime dateObject = DateTime.Now;
[JsonConverter(typeof(TypeInfoConverter))]
public GeoPoint geoPointObject = new GeoPoint() { Latitude = 123456789.123456, Longitude = 123456789.123456 };
[JsonConverter(typeof(TypeInfoConverter))]
public Dictionary<string, string> mapObject = new Dictionary<string, string>();
[JsonConverter(typeof(TypeInfoConverter))]
public Dictionary<string, List<GeoPoint>> mapObjectEx = new Dictionary<string, List<GeoPoint>>()
{{ "1", new List<GeoPoint>() { new GeoPoint() { Latitude = 0.0, Longitude = 0.0 } } }};
[JsonConverter(typeof(TypeInfoConverter))]
public List<GeoPoint> points = new List<GeoPoint>()
{ new GeoPoint() { Latitude=0.0, Longitude=0.0 } };
[JsonConverter(typeof(TypeInfoConverter))]
public Rating rating = Rating.Good;
}
class GeoPoint
{
public double Latitude;
public double Longitude;
}
enum Rating
{
Good,
Bad,
}