问题
Is there a built-in way (or a trick) for parsing only valid objects and ignoring invalid ones?
Not a duplicate
The question Ignoring an invalid field when deserializing json in Json.Net does not answer my question because it's about a custom serializer for a very specific field of date-time type. I'm seeking a generic solution working for any property and any object.
In other words if anything is invalid, just ignore it and contintue to the next entry. As far as json is concerned, the file is correct but the content might not match the expected types in some places. It can by anything.
Background: The file contains an array of many workflows and a single damaged entry should not break the entire configuration and virtually disable them all.
Here's an example demonstrating what I mean. Let's say I have an array of User
s but one entry instead of using a string
for the Name
uses an array (it might by any combination of invalid values, like an object where an array is expected.
I'd like to deserialize this array and ignore entries that couldn't be deserialized. This means that the expected result should be two users, John & Tom.
I tried to use the Error
handler but it does not work this way. It doesn't allow me to skip the errors.
void Main()
{
var json = @"
[
{
'Name': 'John',
},
{
'Name': [ 'John' ]
},
{
'Name': 'Tom',
},
]
";
var users = JsonConvert.DeserializeObject<IEnumerable<User>>(json, new JsonSerializerSettings
{
Error = (sender, e) =>
{
e.Dump();
e.ErrorContext.Handled = true;
e.CurrentObject.Dump();
}
}).Dump();
}
class User
{
public string Name { get; set; }
}
回答1:
I solved this way. Not elegant.
var users = JsonConvert.DeserializeObject<IEnumerable<Object>>(json);
var usersList = users.ToList().Select(x =>
{
try { return JsonConvert.DeserializeObject<User>(JsonConvert.SerializeObject(x)); } catch { return null; }
}
).Where(x=> x != null).ToList<User>();
回答2:
A good example of how I approached a similar situation would be to have a set of different JsonSerializerSettings
configuration specifically within a try
/catch
block.
For example:
JsonSerializerSettings jsonSetting = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore };
The above code block could be done within the catch
section after you try
and failed to complete the parse of the JSON.
Your try
block could have normal error behavior inside that block above:
jsonSetting = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error };
Provides similar error handling, and when that errors, it drops into the catch
block to ignore the missing fields.
However, that depends on whether you're OK with skipping data, or if you want to parse everything. It really is a case-by-case basis dependent on your actual JSON dataset.
Placing this above the try
/catch
blocks, and using jsonSetting
to pass along as needed, depending on your specific dataset.
EDIT: Just for emphasis, I do want to point out that the sample you provided isn't a perfect route to approach using this method, but it did allow me to skip arrays that were null, or had invalid data in my case. It really depends on your dataset, but this may be a useful route to at least pursue or consider.
来源:https://stackoverflow.com/questions/56081519/deserialize-only-valid-objects-by-ignoring-errors