Refactor JSON deserialization in ProcessData classes and improve error handling
This commit is contained in:
@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
@ -44,12 +45,11 @@ public class ProcessData : IProcessData
|
|||||||
{
|
{
|
||||||
List<Description> results = new();
|
List<Description> results = new();
|
||||||
Description? description;
|
Description? description;
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description);
|
||||||
if (description is null)
|
if (description is null)
|
||||||
continue;
|
continue;
|
||||||
results.Add(description);
|
results.Add(description);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
@ -221,12 +222,11 @@ public class ProcessData : IProcessData
|
|||||||
{
|
{
|
||||||
List<Description> results = new();
|
List<Description> results = new();
|
||||||
Description? description;
|
Description? description;
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description);
|
||||||
if (description is null)
|
if (description is null)
|
||||||
continue;
|
continue;
|
||||||
results.Add(description);
|
results.Add(description);
|
||||||
|
|||||||
@ -399,12 +399,11 @@ public class ProcessData : IProcessData
|
|||||||
{
|
{
|
||||||
List<Description> results = new();
|
List<Description> results = new();
|
||||||
Description? description;
|
Description? description;
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description);
|
||||||
if (description is null)
|
if (description is null)
|
||||||
continue;
|
continue;
|
||||||
results.Add(description);
|
results.Add(description);
|
||||||
|
|||||||
@ -615,12 +615,11 @@ public class ProcessData : IProcessData
|
|||||||
{
|
{
|
||||||
List<Description> results = new();
|
List<Description> results = new();
|
||||||
Description? description;
|
Description? description;
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
description = JsonSerializer.Deserialize(jsonElement.ToString(), DescriptionSourceGenerationContext.Default.Description);
|
||||||
if (description is null)
|
if (description is null)
|
||||||
continue;
|
continue;
|
||||||
results.Add(description);
|
results.Add(description);
|
||||||
|
|||||||
@ -143,7 +143,7 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
|
|||||||
let businessValue = workItem.BusinessValue;
|
let businessValue = workItem.BusinessValue;
|
||||||
let timeCriticality = workItem.TimeCriticality;
|
let timeCriticality = workItem.TimeCriticality;
|
||||||
let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement;
|
let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement;
|
||||||
let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? null : workItem.WeightedShortestJobFirst.toFixed(2);
|
let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? ' ' : workItem.WeightedShortestJobFirst.toFixed(2);
|
||||||
workItem.CumulativeStoryPoints = ' ';
|
workItem.CumulativeStoryPoints = ' ';
|
||||||
workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)';
|
workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)';
|
||||||
workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? ' ' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1);
|
workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? ' ' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1);
|
||||||
@ -159,7 +159,11 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
|
|||||||
workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? ' ' : getNotifications(t, data.TimeCriticality);
|
workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? ' ' : getNotifications(t, data.TimeCriticality);
|
||||||
workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? ' ' : getNotifications(r, data.RiskReductionOpportunityEnablement);
|
workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? ' ' : getNotifications(r, data.RiskReductionOpportunityEnablement);
|
||||||
workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder;
|
workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder;
|
||||||
let check = effort == workItem.Effort
|
if (effort == undefined || businessValue == undefined || timeCriticality == undefined || riskReductionMinusOpportunityEnablement || weightedShortestJobFirst == undefined) {
|
||||||
|
workItem.api = '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let check = effort === workItem.Effort
|
||||||
&& businessValue === workItem.BusinessValue
|
&& businessValue === workItem.BusinessValue
|
||||||
&& timeCriticality === workItem.TimeCriticality
|
&& timeCriticality === workItem.TimeCriticality
|
||||||
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement;
|
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement;
|
||||||
@ -167,7 +171,7 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
|
|||||||
workItem.api = '';
|
workItem.api = '';
|
||||||
} else {
|
} else {
|
||||||
workItem.api = `
|
workItem.api = `
|
||||||
### Work Item Patch ${check} WSJF ${workItem.Id} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst}
|
### Work Item Patch ${check} WSJF ${workItem.Id} ${effort}:${workItem.Effort}; ${businessValue}:${workItem.BusinessValue}; ${timeCriticality}:${workItem.TimeCriticality}; ${riskReductionMinusOpportunityEnablement}:${workItem.RiskReductionMinusOpportunityEnablement}; ${weightedShortestJobFirst}:${workItem.WeightedShortestJobFirst};
|
||||||
|
|
||||||
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0
|
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0
|
||||||
Authorization: Basic {{PAT}}
|
Authorization: Basic {{PAT}}
|
||||||
@ -204,18 +208,19 @@ Content-Type: application/json-patch+json
|
|||||||
"path": "/fields/Custom.WSJFFib",
|
"path": "/fields/Custom.WSJFFib",
|
||||||
"value": "${workItem.WeightedShortestJobFirst}"
|
"value": "${workItem.WeightedShortestJobFirst}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
HTTP 200
|
HTTP 200
|
||||||
[Asserts]
|
[Asserts]
|
||||||
header "Content-Type" == "application/json; charset=utf-8; api-version=7.0"
|
header "Content-Type" == "application/json; charset=utf-8; api-version=7.0"
|
||||||
jsonpath "$.id" == ${workItem.Id}
|
jsonpath "$.id" == ${workItem.Id}
|
||||||
jsonpath "$.fields['Microsoft.VSTS.Common.BusinessValue']" == ${workItem.BusinessValue}
|
jsonpath "$.fields['Microsoft.VSTS.Common.BusinessValue']" == ${workItem.BusinessValue}
|
||||||
jsonpath "$.fields['Microsoft.VSTS.Scheduling.Effort']" == ${workItem.Effort}
|
jsonpath "$.fields['Microsoft.VSTS.Scheduling.Effort']" == ${workItem.Effort}
|
||||||
jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportunityEnablement}
|
jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportunityEnablement}
|
||||||
jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality}
|
jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality}
|
||||||
jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst}
|
jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst}
|
||||||
jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`;
|
jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Adaptation.Shared;
|
namespace Adaptation.Shared;
|
||||||
@ -447,12 +446,13 @@ public class FileRead : Properties.IFileRead
|
|||||||
{
|
{
|
||||||
List<Properties.IDescription> results = new();
|
List<Properties.IDescription> results = new();
|
||||||
Duplicator.Description description;
|
Duplicator.Description description;
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
description = JsonSerializer.Deserialize<Duplicator.Description>(jsonElement.ToString(), jsonSerializerOptions);
|
description = JsonSerializer.Deserialize(jsonElement.ToString(), Duplicator.SharedDescriptionSourceGenerationContext.Default.Description);
|
||||||
|
if (description is null)
|
||||||
|
continue;
|
||||||
results.Add(description);
|
results.Add(description);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
@ -654,6 +654,17 @@ internal class ProcessDataStandardFormat
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static JsonElement[] GetArray(string reportFullPath, string[] lines, ProcessDataStandardFormat processDataStandardFormat)
|
||||||
|
{
|
||||||
|
JsonElement[] results;
|
||||||
|
string? json = GetRecordsJson(reportFullPath, lines);
|
||||||
|
if (string.IsNullOrEmpty(json))
|
||||||
|
results = GetArray(processDataStandardFormat);
|
||||||
|
else
|
||||||
|
results = JsonSerializer.Deserialize(json, JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
|
internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
@ -903,7 +914,7 @@ internal class ProcessDataStandardFormat
|
|||||||
}
|
}
|
||||||
foreach (KeyValuePair<string, List<string>> keyValuePair in results)
|
foreach (KeyValuePair<string, List<string>> keyValuePair in results)
|
||||||
{
|
{
|
||||||
if (body.Count < 3)
|
if (body.Count < 2)
|
||||||
break;
|
break;
|
||||||
if (keyValuePair.Value.Count != body.Count)
|
if (keyValuePair.Value.Count != body.Count)
|
||||||
continue;
|
continue;
|
||||||
@ -956,6 +967,26 @@ internal class ProcessDataStandardFormat
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string? GetRecordsJson(string reportFullPath, string[] lines)
|
||||||
|
{
|
||||||
|
string? result;
|
||||||
|
bool foundRecords = false;
|
||||||
|
List<string> results = new();
|
||||||
|
lines ??= File.ReadAllLines(reportFullPath);
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
if (line.StartsWith("\"Records\""))
|
||||||
|
foundRecords = true;
|
||||||
|
if (!foundRecords)
|
||||||
|
continue;
|
||||||
|
if (line == "],")
|
||||||
|
break;
|
||||||
|
results.Add(line);
|
||||||
|
}
|
||||||
|
result = results.Count == 0 ? null : $"{string.Join(Environment.NewLine, results.Skip(1))}{Environment.NewLine}]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
|||||||
Reference in New Issue
Block a user