如何在使用JSON反序列化时显示十进制值.. NET在Azure APIM?



我使用Azure APIM策略表达式来聚合多个响应。在响应中有一些十进制值。但是在反序列化过程中,格式发生了更改,如输出所示。我想返回Input

输入>
{
"x1": 1.55391E4,
"x2": 2.2173244E5,
"x3": 1.11226E3,
"UpdatedDateTime": "2023-01-17T20:45:51.959+08:00"
}

{
"x1": 15539.1,
"x2": 221732.44,
"x3": 1112.26,
"UpdatedDateTime": "2023-01-17T20:45:51.959+08:00"
}

预期

{
"x1": 1.55391E4,
"x2": 2.2173244E5,
"x3": 1.11226E3,
"UpdatedDateTime": "2023-01-17T20:45:51.959+08:00"
}

这是我的小提琴

在这个示例中,我保留了带有Offset的DateTimeZone。但我不能处理十进制字段(x1 x2 x3)我只是想像输入一样返回。

请注意,我是在一个策略表达式中写的,所以我不能创建任何c#扩展或帮助方法。

JToken层次结构中强制使用decimal值的科学符号的一种方法是用适当格式的JRaw值替换十进制值的JValue标记:

var settings = new JsonSerializerSettings 
{
// Make sure that FloatParseHandling is consistent with the later check ".Where(v => v.Value is decimal)"
FloatParseHandling = FloatParseHandling.Decimal, 
FloatFormatHandling = FloatFormatHandling.DefaultValue, 
// Instead of DateParseHandling.DateTimeOffset, you could use DateParseHandling.None to skip DateTime recognition and leave date/time strings unchanged.
DateParseHandling = DateParseHandling.DateTimeOffset, 
DateTimeZoneHandling = DateTimeZoneHandling.Unspecified
};
var obj = JsonConvert.DeserializeObject<JObject>(json, settings);
var decimalValues = obj.Descendants().OfType<JValue>().Where(v => v.Value is decimal).ToList(); 
foreach (var value in decimalValues)
{
value.Replace(new JRaw(((decimal)value.Value).ToString("0.00000E0" /*, System.Globalization.CultureInfo.InvariantCulture */))); // Is System.Globalization.CultureInfo.InvariantCulture available?
}
var newJson = obj.ToString(Formatting.Indented);

结果是

{
"x1": 1.55391E4,
"x2": 2.21732E5,
"x3": 1.11226E3,
"UpdatedDateTime": "2023-01-17T20:45:51.959+08:00"
}

在这里演示小提琴#1。

指出:

  • 您的代码在Azure APIM策略表达式中。在这样的表达式中只允许非常有限的一组类型,正如. net框架中策略表达式中允许的类型所记录的那样。值得注意的是,以下是不可用的:

    • Newtonsoft.Json.JsonConverter.
    • Newtonsoft.Json.JsonTextReaderJsonTextWriter.
    • System.Text.Json(all).

    缺乏任何创建自定义转换器的能力,这就是我建议使用JRaw的原因。

  • 你不能在Json.NET中保留原始的十进制格式。当JsonTextReader遇到浮点JSON数时,将其解析为decimaldouble,并且丢弃原始JSON字符序列. 因此,仅保留值(decimal的情况下为位数)。

  • Utf8JsonReaderfrom System.Text。另一方面,Json保留了底层的Json字符序列。这个字符序列被传递给JsonElementJsonNode,它们也保留了原始字符序列,并呈现它的只读(或可编辑)视图。因此,如果Azure APIM策略表达式被增强以允许System.Text.Json,您将能够更容易地保留原始的JSON十进制格式。

    在这里演示小提琴#2。

  • 如果你想留下所有的日期&时间字符串值不变,而不是DateParseHandling.DateTimeOffset,您可以使用DateParseHandling.None来完全禁用日期时间识别。