泛型和复杂类型的 JsonConverter 失败 "Additional text found in JSON...."
JsonConverter of generic and complex type fails "Additional text found in JSON...."
我正在尝试使用 json 转换器但没有成功。
我有一个传感器 class 可以(反)序列化 json:
internal class JsonSensor<T> : IJsonSensor where T : struct
{
[JsonProperty(PropertyName = "value")]
public T Value { get; set; }
[JsonProperty(PropertyName = "state")]
public SensorState State { get; set; } = SensorState.Unknown;
public override string ToString()
{
return $"Value={Value}; State={State}";
}
}
然后我有一长串传感器,我将专注于第一个,为了简单起见忽略其余的:
[Function(Name = "sensors")]
internal class Sensors
{
[CabinetDoubleSensor(DisplayName=CabinetSensorNames.RcwPcwSupPrs, SensorType = SensorType.PressureInBar, Precision=2)]
[JsonProperty(PropertyName = "IO_PCW_FL_SPR")]
[JsonConverter(typeof(BarToPascalConverter))]
public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>();
[CabinetDoubleSensor(DisplayName=CabinetSensorNames.RcwPcwRetPrs, SensorType = SensorType.PressureInBar, Precision=2)]
[JsonProperty(PropertyName = "IO_PCW_RL_SPR")]
[JsonConverter(typeof(BarToPascalConverter))]
public JsonSensor<double> IOPcwRlSpr { get; set; } = new JsonSensor<double>();
...
...
...
}
而且,我有转换器可以将值从一种公制转换为另一种。例如。 BarToPascal
转换器:
internal class BarToPascalConverter : FactorConverterBase
{
public BarToPascalConverter() : base(1e5)
{
}
}
internal abstract class FactorConverterBase : JsonConverter<JsonSensor<double>>
{
public double Factor { get; protected set; }
protected FactorConverterBase(double factor)
{
Factor = factor;
}
public override void WriteJson(JsonWriter writer, JsonSensor<double> value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var o = reader.Value;
//existingValue.Value = ((JsonSensor<double>)reader.Value).Value / Factor;
return new JsonSensor<double>();
}
}
问题出在ReadJson方法中。我做错了什么导致以下异常:
Newtonsoft.Json.JsonSerializationException :完成反序列化对象后,在 JSON 字符串中找到其他文本。路径 '',第 1 行,位置 45.
我写了一个单元测试来隔离问题,并为 ReadJson 方法尝试不同的实现,但我发现即使我 'just return' 一个新的 JsonSensor<double>()
反序列化仍然失败。
当然,当我删除 JsonConverter 时,我可以反序列化字符串。所以这告诉我:
- 提供的 json 字符串是可以的。
- json 反序列化的 class 结构是可以的。
我在 ReadJson 中做错了什么?如何从 reader 成功读取 JsonSensor<double>
并转换其值?
为了单元测试的完整性:
[TestFixture]
public class GetSensorsTests
{
[Test]
public void GetSensors()
{
const string test = "{\"IO_PCW_FL_SPR\" : {\"value\":123.0,\"state\":1}}";
var sensors = JsonConvert.DeserializeObject<Sensors>(test);
Assert.AreEqual(123.0, sensors.IOPcwFlSpr.Value, 0.00001);
}
}
这似乎可行,但不确定这是否是预期的工作方式。
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var jsonObject=JObject.Load(reader);
var s = JsonConvert.DeserializeObject<JsonSensor<double>>(jsonObject.ToString());
s.Value = s.Value / Factor;
return s;
}
dbc评论后更新:
public override void WriteJson(JsonWriter writer, JsonSensor<double> value, JsonSerializer serializer)
{
value.Value = value.Value * Factor;
var json = JsonConvert.SerializeObject(value);
writer.WriteValue(json);
}
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var jsonSensor = JObject.Load(reader).ToObject<JsonSensor<double>>();
jsonSensor.Value = jsonSensor.Value / Factor;
return jsonSensor;
}
我正在尝试使用 json 转换器但没有成功。
我有一个传感器 class 可以(反)序列化 json:
internal class JsonSensor<T> : IJsonSensor where T : struct
{
[JsonProperty(PropertyName = "value")]
public T Value { get; set; }
[JsonProperty(PropertyName = "state")]
public SensorState State { get; set; } = SensorState.Unknown;
public override string ToString()
{
return $"Value={Value}; State={State}";
}
}
然后我有一长串传感器,我将专注于第一个,为了简单起见忽略其余的:
[Function(Name = "sensors")]
internal class Sensors
{
[CabinetDoubleSensor(DisplayName=CabinetSensorNames.RcwPcwSupPrs, SensorType = SensorType.PressureInBar, Precision=2)]
[JsonProperty(PropertyName = "IO_PCW_FL_SPR")]
[JsonConverter(typeof(BarToPascalConverter))]
public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>();
[CabinetDoubleSensor(DisplayName=CabinetSensorNames.RcwPcwRetPrs, SensorType = SensorType.PressureInBar, Precision=2)]
[JsonProperty(PropertyName = "IO_PCW_RL_SPR")]
[JsonConverter(typeof(BarToPascalConverter))]
public JsonSensor<double> IOPcwRlSpr { get; set; } = new JsonSensor<double>();
...
...
...
}
而且,我有转换器可以将值从一种公制转换为另一种。例如。 BarToPascal
转换器:
internal class BarToPascalConverter : FactorConverterBase
{
public BarToPascalConverter() : base(1e5)
{
}
}
internal abstract class FactorConverterBase : JsonConverter<JsonSensor<double>>
{
public double Factor { get; protected set; }
protected FactorConverterBase(double factor)
{
Factor = factor;
}
public override void WriteJson(JsonWriter writer, JsonSensor<double> value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var o = reader.Value;
//existingValue.Value = ((JsonSensor<double>)reader.Value).Value / Factor;
return new JsonSensor<double>();
}
}
问题出在ReadJson方法中。我做错了什么导致以下异常:
Newtonsoft.Json.JsonSerializationException :完成反序列化对象后,在 JSON 字符串中找到其他文本。路径 '',第 1 行,位置 45.
我写了一个单元测试来隔离问题,并为 ReadJson 方法尝试不同的实现,但我发现即使我 'just return' 一个新的 JsonSensor<double>()
反序列化仍然失败。
当然,当我删除 JsonConverter 时,我可以反序列化字符串。所以这告诉我:
- 提供的 json 字符串是可以的。
- json 反序列化的 class 结构是可以的。
我在 ReadJson 中做错了什么?如何从 reader 成功读取 JsonSensor<double>
并转换其值?
为了单元测试的完整性:
[TestFixture]
public class GetSensorsTests
{
[Test]
public void GetSensors()
{
const string test = "{\"IO_PCW_FL_SPR\" : {\"value\":123.0,\"state\":1}}";
var sensors = JsonConvert.DeserializeObject<Sensors>(test);
Assert.AreEqual(123.0, sensors.IOPcwFlSpr.Value, 0.00001);
}
}
这似乎可行,但不确定这是否是预期的工作方式。
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var jsonObject=JObject.Load(reader);
var s = JsonConvert.DeserializeObject<JsonSensor<double>>(jsonObject.ToString());
s.Value = s.Value / Factor;
return s;
}
dbc评论后更新:
public override void WriteJson(JsonWriter writer, JsonSensor<double> value, JsonSerializer serializer)
{
value.Value = value.Value * Factor;
var json = JsonConvert.SerializeObject(value);
writer.WriteValue(json);
}
public override JsonSensor<double> ReadJson(JsonReader reader, Type objectType, JsonSensor<double> existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var jsonSensor = JObject.Load(reader).ToObject<JsonSensor<double>>();
jsonSensor.Value = jsonSensor.Value / Factor;
return jsonSensor;
}