C# 使用Newtonsoft ToObject反序列化许多Json文件
这里有效率很低的东西吗?这一过程似乎比应该的时间要长。我正在解析许多JSON文件,每个文件都有一个JsonArray对象。也许有经验的人可以指出这种将JSON解析为对象的方法中的一个错误,从而为我节省大量时间 此外,内存使用缓慢地一个接一个地增加,有时会导致OutOfMemory异常C# 使用Newtonsoft ToObject反序列化许多Json文件,c#,.net,json,json.net,C#,.net,Json,Json.net,这里有效率很低的东西吗?这一过程似乎比应该的时间要长。我正在解析许多JSON文件,每个文件都有一个JsonArray对象。也许有经验的人可以指出这种将JSON解析为对象的方法中的一个错误,从而为我节省大量时间 此外,内存使用缓慢地一个接一个地增加,有时会导致OutOfMemory异常 public void Parse(){ using (BabysFirstsUsersDataEntities db = new BabysFirstsUsersDataEntities() {
public void Parse(){
using (BabysFirstsUsersDataEntities db = new BabysFirstsUsersDataEntities()
{
foreach (var path in Directory.EnumerateFiles(@"C:\\examplepath\").OrderBy(f => f))
{
string jsonString = System.IO.File.ReadAllText(path);
JToken tok = JObject.Parse(jsonString);
Debug.WriteLine("path: " + path);
foreach (var x in tok.First.First)
{
JsonUserImageDTO jdto = x.ToObject<JsonUserImageDTO>();
UserImageList uil = jdto.ToDataModel();
if (uil.REID != null)
db.UserImageLists.Add(uil);
}
}
db.SaveChanges();
}
}
您可以创建对象,然后反序列化它们。 例如:
JsonConvert.DeserializeObject<RootObject>(jsonString);
public class Asdf
{
public bool read { get; set; }
public bool write { get; set; }
}
public class RoleAdmin
{
public bool read { get; set; }
}
public class ACL
{
public Asdf asdf { get; set; }
public RoleAdmin { get; set; }
}
public class Result
{
public ACL ACL { get; set; }
public string REID { get; set; }
public string createdAt { get; set; }
public string email { get; set; }
public string objectId { get; set; }
public string updatedAt { get; set; }
public int urlCount { get; set; }
public List<string> urlList { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
JsonConvert.DeserializeObject(jsonString);
公共类Asdf
{
公共bool read{get;set;}
公共bool write{get;set;}
}
公共类RoleAdmin
{
公共bool read{get;set;}
}
公共类ACL
{
公共Asdf Asdf{get;set;}
public RoleAdmin{get;set;}
}
公开课成绩
{
公共ACL ACL{get;set;}
公共字符串REID{get;set;}
公共字符串createdAt{get;set;}
公共字符串电子邮件{get;set;}
公共字符串objectId{get;set;}
公共字符串updatedAt{get;set;}
public int urlCount{get;set;}
公共列表urlList{get;set;}
}
公共类根对象
{
公共列表结果{get;set;}
}
您可以创建对象,然后反序列化它们。
例如:
JsonConvert.DeserializeObject<RootObject>(jsonString);
public class Asdf
{
public bool read { get; set; }
public bool write { get; set; }
}
public class RoleAdmin
{
public bool read { get; set; }
}
public class ACL
{
public Asdf asdf { get; set; }
public RoleAdmin { get; set; }
}
public class Result
{
public ACL ACL { get; set; }
public string REID { get; set; }
public string createdAt { get; set; }
public string email { get; set; }
public string objectId { get; set; }
public string updatedAt { get; set; }
public int urlCount { get; set; }
public List<string> urlList { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
JsonConvert.DeserializeObject(jsonString);
公共类Asdf
{
公共bool read{get;set;}
公共bool write{get;set;}
}
公共类RoleAdmin
{
公共bool read{get;set;}
}
公共类ACL
{
公共Asdf Asdf{get;set;}
public RoleAdmin{get;set;}
}
公开课成绩
{
公共ACL ACL{get;set;}
公共字符串REID{get;set;}
公共字符串createdAt{get;set;}
公共字符串电子邮件{get;set;}
公共字符串objectId{get;set;}
公共字符串updatedAt{get;set;}
public int urlCount{get;set;}
公共列表urlList{get;set;}
}
公共类根对象
{
公共列表结果{get;set;}
}
看起来可能有几个地方会导致速度缓慢
jdto
,然后uil
)tok
。有关如何使用流,请参见第二个示例。实际上,在您的例子中,您在内存中保存了4次相同的信息——字符串、tok
、jdto
和uil
。这就引出了下一点EnumerateFiles()
的部分。如果您不打算对文件执行任何操作,那么反序列化文件是没有意义的看起来可能有几个地方会导致速度变慢
jdto
,然后uil
)tok
。有关如何使用流,请参见第二个示例。实际上,在您的例子中,您在内存中保存了4次相同的信息——字符串、tok
、jdto
和uil
。这就引出了下一点EnumerateFiles()
的部分。如果您不打算对文件执行任何操作,那么反序列化文件是没有意义的你真的分析过你的代码吗?请参阅Erik Lippert的:在开始调查备选方案之前,使用探查器或其他分析工具以经验方式确定瓶颈在哪里。例如,您的实际性能问题可能在
BabysFirstsUsersDataEntities db
类中的某个地方
话虽如此,我的直接反应是,数据的中间表示太多了,构建、人口和垃圾收集都需要时间。这些措施包括:
可能足够大,可以继续运行,从而永久性地影响进程的性能和内存使用jsonString
- 整个JSON层次结构的
表示JToken-tok
- 每个人
JsonUserImageDTO
BabyFirstSusersDataEntities
看起来像这样(我只是在这里猜测):
通过填充预先分配的
rootDTO
和ConvertingCollection
,您的db.userImageList
将被JSON的内容填充,中间表示形式更少。您实际分析过代码吗?请参阅Erik Lippert的:使用剖析器或其他分析工具来确定经验数据
public class BabysFirstsUsersDataEntities
{
public BabysFirstsUsersDataEntities() { this.UserImageLists = new List<UserImageList>(); }
public List<UserImageList> UserImageLists { get; set; }
}
public class UserImageList
{
public string email { get; set; }
public List<string> urlList;
}
public class RootObjectDTO
{
public ICollection<JsonUserImageDTO> results { get; set; }
}
public class JsonUserImageDTO
{
public ACL ACL { get; set; }
public string REID { get; set; }
public string createdAt { get; set; }
public string email { get; set; }
public string objectId { get; set; }
public string updatedAt { get; set; }
public int urlCount { get; set; }
public List<string> urlList { get; set; }
public UserImageList ToDataModel()
{
return new UserImageList { email = email, urlList = urlList };
}
}
public class Asdf
{
public bool read { get; set; }
public bool write { get; set; }
}
public class RoleAdmin
{
public bool read { get; set; }
}
public class ACL
{
public Asdf asdf { get; set; }
[JsonProperty("role:admin")]
public RoleAdmin RoleAdmin { get; set; }
}
public class ConvertingCollection<TIn, TOut> : BaseConvertingCollection<TIn, TOut, ICollection<TIn>>
{
readonly Func<TOut, TIn> toInner;
public ConvertingCollection(Func<ICollection<TIn>> getCollection, Func<TIn, TOut> toOuter, Func<TOut, TIn> toInner)
: base(getCollection, toOuter)
{
if (toInner == null)
throw new ArgumentNullException();
this.toInner = toInner;
}
protected TIn ToInner(TOut outer) { return toInner(outer); }
public override void Add(TOut item)
{
Collection.Add(ToInner(item));
}
public override void Clear()
{
Collection.Clear();
}
public override bool IsReadOnly { get { return Collection.IsReadOnly; } }
public override bool Remove(TOut item)
{
return Collection.Remove(ToInner(item));
}
public override bool Contains(TOut item)
{
return Collection.Contains(ToInner(item));
}
}
public abstract class BaseConvertingCollection<TIn, TOut, TCollection> : ICollection<TOut>
where TCollection : ICollection<TIn>
{
readonly Func<TCollection> getCollection;
readonly Func<TIn, TOut> toOuter;
public BaseConvertingCollection(Func<TCollection> getCollection, Func<TIn, TOut> toOuter)
{
if (getCollection == null || toOuter == null)
throw new ArgumentNullException();
this.getCollection = getCollection;
this.toOuter = toOuter;
}
protected TCollection Collection { get { return getCollection(); } }
protected TOut ToOuter(TIn inner) { return toOuter(inner); }
#region ICollection<TOut> Members
public abstract void Add(TOut item);
public abstract void Clear();
public virtual bool Contains(TOut item)
{
var comparer = EqualityComparer<TOut>.Default;
foreach (var member in Collection)
if (comparer.Equals(item, ToOuter(member)))
return true;
return false;
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
public int Count { get { return Collection.Count; } }
public abstract bool IsReadOnly { get; }
public abstract bool Remove(TOut item);
#endregion
#region IEnumerable<TOut> Members
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in Collection)
yield return ToOuter(item);
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
var rootDTO = new RootObjectDTO
{
results = new ConvertingCollection<UserImageList, JsonUserImageDTO>(() => db.UserImageLists, (x) => { throw new NotImplementedException(); }, (x) => x.ToDataModel())
};
using (var stream = File.Open(path, FileMode.Open))
using (var reader = new StreamReader(stream))
{
JsonSerializer.CreateDefault().Populate(reader, rootDTO);
}