我有两个JSON文件(我无法更改格式),格式如下:
主要档案 -
[
{
"Name":"XYZ",
"UnitReferenceId":1
},
{
"Name":"ABC",
"UnitReferenceId":2
}
]
查找/引用JSON文件 -
[
{
"UnitReferenceId":1,
"Units":[
{
"Unit":"mg",
"Scale":1
},
{
"Unit":"gm",
"Scale":1000
},
{
"Unit":"kg",
"Scale":1000000
}
]
},
{
"UnitReferenceId":2,
"Units":[
{
"Unit":"mm",
"Scale":1
},
{
"Unit":"m",
"Scale":1000
},
{
"Unit":"km",
"Scale":1000000
}
]
}
]
我如何使用Newtonsoft JSON将其反序列化为C#类,如下所示:
public class Widget
{
public string Name {get; set;}
public UnitReference UnitReference { get; set; }
}
public class UnitReference
{
public long UnitReferenceId { get; set; }
public List<Unit> Units { get; set; }
}
public class Unit
{
[JsonProperty("Unit")]
public string UnitValue { get; set; }
public long Scale { get; set; }
}
非常感谢任何帮助!
答案 0 :(得分:0)
您可以通过读取两个JSON文件来执行此操作:
首先将UnitReference
的查找/引用JSON文件作为List<UnitReference>
读取,然后转换为Dictionary<long, UnitReference>
查找表。
接下来,使用Widget
Dictionary<long, UnitReference>
读取主文件,该UnitReferenceId
传递UnitReference
查找表,并可在public class UnitReference
{
readonly long unitReferenceId;
public UnitReference(long unitReferenceId)
{
this.unitReferenceId = unitReferenceId;
}
public long UnitReferenceId { get { return unitReferenceId; } }
public List<Unit> Units { get; set; }
}
public class Unit
{
[JsonProperty("Unit")]
public string UnitValue { get; set; }
public long Scale { get; set; }
}
public class Widget
{
public string Name { get; set; }
public UnitReference UnitReference { get; set; }
}
和{{1}之间进行转换在阅读和写作过程中。
因此,您的课程将如下所示:
UnitReferenceId
(我唯一的修改是让public class WidgetConverter : CustomPropertyConverterBase<Widget>
{
readonly IDictionary<long, UnitReference> units;
public WidgetConverter(IDictionary<long, UnitReference> units)
{
this.units = units;
}
protected override void ReadCustomProperties(JObject obj, Widget value, JsonSerializer serializer)
{
var id = (long?)obj.GetValue("UnitReferenceId", StringComparison.OrdinalIgnoreCase);
if (id != null)
value.UnitReference = units[id.Value];
}
protected override bool ShouldSerialize(JsonProperty property, object value)
{
if (property.UnderlyingName == nameof(Widget.UnitReference))
return false;
return base.ShouldSerialize(property, value);
}
protected override void WriteCustomProperties(JsonWriter writer, Widget value, JsonSerializer serializer)
{
if (value.UnitReference != null)
{
writer.WritePropertyName("UnitReferenceId");
writer.WriteValue(value.UnitReference.UnitReferenceId);
}
}
}
public abstract class CustomPropertyConverterBase<T> : JsonConverter where T : class
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jObj = JObject.Load(reader);
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
var value = existingValue as T ?? (T)contract.DefaultCreator();
ReadCustomProperties(jObj, value, serializer);
// Populate the remaining properties.
using (var subReader = jObj.CreateReader())
{
serializer.Populate(subReader, value);
}
return value;
}
protected abstract void ReadCustomProperties(JObject obj, T value, JsonSerializer serializer);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(value.GetType());
writer.WriteStartObject();
foreach (var property in contract.Properties.Where(p => ShouldSerialize(p, value)))
{
var propertyValue = property.ValueProvider.GetValue(value);
if (propertyValue == null && serializer.NullValueHandling == NullValueHandling.Ignore)
continue;
writer.WritePropertyName(property.PropertyName);
serializer.Serialize(writer, propertyValue);
}
WriteCustomProperties(writer, (T)value, serializer);
writer.WriteEndObject();
}
protected virtual bool ShouldSerialize(JsonProperty property, object value)
{
return property.Readable && !property.Ignored && (property.ShouldSerialize == null || property.ShouldSerialize(value));
}
protected abstract void WriteCustomProperties(JsonWriter writer, T value, JsonSerializer serializer);
}
成为只读,以便它可以安全地用作字典键。)
然后,定义以下转换器:
var units = JsonConvert.DeserializeObject<List<UnitReference>>(unitsJsonString)
.ToDictionary(u => u.UnitReferenceId);
var settings = new JsonSerializerSettings
{
Converters = { new WidgetConverter(units) },
};
var widgets = JsonConvert.DeserializeObject<List<Widget>>(widgetsJsonString, settings);
反序列化如下:
CustomPropertyConverterBase<T>
注意:
这里我是为了演示目的从JSON字符串反序列化,但您可以直接从您的文件反序列化,如custom JsonConverter
所示。
WidgetConverter
的基类WidgetConverter
自动读取和写入要(反)序列化的对象的所有属性。 UnitReference
然后仅覆盖Widget
属性的此行为,从而无需手动序列化Character lastChar = calculation.charAt(calculation.length()-1);
的所有剩余属性。
答案 1 :(得分:0)
我使用json2csharp快速创建我的课程。如果您必须在代码中实现它,请参阅JSON C# Class Generator Project。