I have the following models:
class CheckResponse
{
public ICollection<CheckModel> Checks { get; set; }
}
public class CheckModel
{
[JsonConverter(typeof(StringEnumConverter))]
public CheckCodes CheckCode { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public ResultCode ResultCode { get; set; }
}
public enum CheckCodes
{
FirstCheck,
SecondCheck,
ThirdCheck,
}
public enum ResultCode
{
Failure,
Success,
Warning
}
I need to convert Checks
into CheckList
:
class CheckList
{
[JsonProperty(nameof(CheckCodes.FirstCheck))]
public bool FirstCheckPassed { get; set; }
[JsonProperty(nameof(CheckCodes.SecondCheck))]
public bool SecondCheckPassed { get; set; }
[JsonProperty(nameof(CheckCodes.ThirdCheck))]
public bool ThirdCheckPassed { get; set; }
}
Example:
class Program
{
static void Main(string[] args)
{
var response = GetResponse();
var checkResponse = JsonConvert.DeserializeObject<CheckResponse>(response);
// var checkList = ?
}
static string GetResponse() => @"{
'checks': [
{
'checkCode': 0,
'resultCode': 1
},
{
'checkCode': 1,
'resultCode': 2
},
{
'checkCode': 2,
'resultCode': 0
}
]}";
}
If resultCode
equals 2 (ResultCode.Warning
) then check should be passed.
So, the checkList
should have following properties values:
FirstCheckPassed = true
SecondCheckPassed = true
ThirdCheckPassed = false
UPDATED:
My solution as follows:
static void Main(string[] args)
{
Test();
}
static IEnumerable<string> Yield(ICollection<CheckModel> checks)
{
foreach (var check in checks)
{
var success = check.ResultCode == ResultCode.Success || check.ResultCode == ResultCode.Warning;
yield return "'" + check.CheckCode.ToString() + "': '" + success.ToString() + "'";
}
}
static void Test()
{
var response = GetResponse();
var checkResponse = JsonConvert.DeserializeObject<CheckResponse>(response);
var o = "{" + string.Join(",", Yield(checkResponse.Checks)) + "}";
var checkList = JsonConvert.DeserializeObject<CheckList>(o);
}
But I'm not sure that this is the best one (Actually, I consider it a little bit ugly). Are there any better approaches?
You can create your own JsonConverter, with additional change to the POCO you can Deserialize to the exact object you want.
Little change into CheckResponse
class CheckResponse
{
[JsonConverter(typeof(CheckModelConverter))]
public CheckList Checks { get; set; }
}
Adding custom converter
public class CheckModelConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = serializer.Deserialize<CheckModel[]>(reader);
var result = new CheckList();
foreach (var item in obj)
{
bool resultValue = item.ResultCode != ResultCode.Failure;
switch (item.CheckCode)
{
case CheckCodes.FirstCheck:
result.FirstCheckPassed = resultValue;
break;
case CheckCodes.SecondCheck:
result.SecondCheckPassed = resultValue;
break;
case CheckCodes.ThirdCheck:
result.ThirdCheckPassed = resultValue;
break;
default:
throw new Exception("No checkcode of " + item.CheckCode);
}
}
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Disclosure: I will love more to actually deserialize it to the exact model, and only then Map it (or part of it) into the type i want, this give me more future flexibility and preserve the actual model structure.
Edit: Fixed spelling in Disclosure.