[英]Unexpected initial token 'EndObject' when populating object exception deserializing abstract class
I wrote a custom JSON converter class in json.net and cannot figure out why I am getting the following exception when I deserialize with it. 我在json.net中编写了一个自定义的JSON转换器类,并且在我用它反序列化时无法弄清楚为什么我得到以下异常。
Unexpected initial token 'EndObject' when populating object.
填充对象时出现意外的初始标记'EndObject'。 Expected JSON object or array.
预期的JSON对象或数组。 Path '', line 1, position 177.
路径'',第1行,第177位。
I have other converters in my project which are modeled very similar which work without issue so I am unsure why this is being such a problem. 我的项目中有其他转换器,模型非常相似,没有问题,所以我不确定为什么这是一个问题。
Here is the object being serialized: 这是被序列化的对象:
[JsonConverter(typeof(CreateCRMIntegrationPromptJsonConverter))]
public abstract class CreateCRMIntegrationDirectPromptBaseBindingModel
{
public bool IncludeInOutput { get; set; }
public string Label { get; set; }
public string Value { get; set; }
public IValidateCRMField Validator { get; set; }
public string ValidatorType { get; set; }
public CRMIntegrationDirectPromptType Type { get; set; }
}
public class CreateCRMIntegrationPromptMobilePhoneBindingModel : CreateCRMIntegrationDirectPromptBaseBindingModel
{
public bool FormatPhoneNumber { get; set; }
}
And the converter 和转换器
public class CreateCRMIntegrationPromptJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Models.CreateCRMIntegrationDirectPromptBaseBindingModel);
}
public override bool CanWrite { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
JObject jo = JObject.Load(reader);
JsonReader jsonReader = jo.CreateReader();
Dictionary<string, string> values = new Dictionary<string, string>(jo.ToObject<IDictionary<string, string>>(), StringComparer.CurrentCultureIgnoreCase);
var typeValue = values["type"].ToString();
Models.CRMIntegrationDirectPromptType integrationPromptType = Models.CRMIntegrationDirectPromptType.Label;
if (!Enum.TryParse(typeValue, out integrationPromptType))
{
integrationPromptType = Models.CRMIntegrationDirectPromptType.Label;
}
switch (integrationPromptType)
{
.........
case Models.CRMIntegrationDirectPromptType.MobilePhone:
Models.CreateCRMIntegrationPromptMobilePhoneBindingModel cRMIntegrationPromptMobilePhoneReturnModel = new Models.CreateCRMIntegrationPromptMobilePhoneBindingModel();
serializer.Populate(reader, cRMIntegrationPromptMobilePhoneReturnModel);
return cRMIntegrationPromptMobilePhoneReturnModel;
.........
}
}
catch(Exception ex)
{
Models.CreateCRMIntegrationPromptLabelBindingModel cRMIntegrationPromptLabelReturnModelDefault = new Models.CreateCRMIntegrationPromptLabelBindingModel();
cRMIntegrationPromptLabelReturnModelDefault.IncludeInOutput = false;
cRMIntegrationPromptLabelReturnModelDefault.Label = string.Empty;
cRMIntegrationPromptLabelReturnModelDefault.Type = Models.CRMIntegrationDirectPromptType.Label;
return cRMIntegrationPromptLabelReturnModelDefault;
}
}
}
When I test with this code I can catch the exception 当我用这段代码测试时,我可以捕获异常
var obj = new CreateCRMIntegrationPromptMobilePhoneBindingModel();
obj.IncludeInOutput = true;
obj.FormatPhoneNumber = true;
obj.Label = "Test";
obj.ValidatorType = "Answer1APILib.CRMIntegration.ValidateCRMField_NonRequired";
obj.Type = CRMIntegrationDirectPromptType.Label;
obj.Value = "";
var test = JsonConvert.SerializeObject(obj);
var output = JsonConvert.DeserializeObject<CreateCRMIntegrationDirectPromptBaseBindingModel>(test);
Here is the JSON returned by the serialization 这是序列化返回的JSON
{
"FormatPhoneNumber":true,
"IncludeInOutput":true,
"Label":"Test",
"Value":"",
"Validator":null,
"ValidatorType":"Answer1APILib.CRMIntegration.ValidateCRMField_NonRequired",
"Type":0
}
You need to pass the jsonReader
to serializer.Populate()
rather than the incoming reader
. 您需要将
jsonReader
传递给serializer.Populate()
而不是传入的reader
。 Or eliminate the variable jsonReader
entirely and pass in jo.CreateReader()
: 或者完全消除变量
jsonReader
并传入jo.CreateReader()
:
serializer.Populate(jo.CreateReader(), cRMIntegrationPromptMobilePhoneReturnModel);
You need to do this because you previously loaded the object at the initial location of the incoming JsonReader reader
into JObject jo
: 您需要这样做是因为您之前将传入的
JsonReader reader
的初始位置的对象加载到JObject jo
:
JObject jo = JObject.Load(reader);
Thus the incoming reader
has been advanced past the object and on to whatever comes next. 因此,传入的
reader
已经超越了对象,并进入下一步。 Using the reader
a second time to populate you model will advance the reader further still, eventually causing the Unexpected initial token 'EndObject'
you are seeing. 第二次使用
reader
填充模型将进一步推动阅读器,最终导致您看到的Unexpected initial token 'EndObject'
。
You might also want to check to see whether the incoming JSON token is null
before loading it as an object: 在将其作为对象加载之前,您可能还需要检查传入的JSON标记是否为
null
:
if (reader.TokenType == JsonToken.Null)
return null;
JObject jo = JObject.Load(reader);
Since a null
value in JSON file is actually loaded as a non-null JValue
with JValue.Type
equal to JTokenType.Null
, attempting to load such a token as a JObject
will fail. 由于JSON文件中的
null
值实际上是作为非空JValue
加载的,其JValue.Type
等于JTokenType.Null
,因此尝试将此类标记加载为JObject
将失败。
(Finally, I'm not sure I would handle exceptions in ReadJson()
itself. Newtonsoft already has a mechanism for handling exceptions and if you catch and swallow all exceptions inside ReadJson()
rather than using the mechanism there's a chance you could fall into an infinite loop when reading a malformed, truncated JSON file. This is not the primary cause of the problem you are seeing though.) (最后,我不确定我是否会处理
ReadJson()
本身的异常ReadJson()
已经有了处理异常的机制 ,如果你捕获并吞下ReadJson()
所有异常而不是使用该机制,那么你有可能陷入读取格式错误的截断JSON文件时出现无限循环。这不是您遇到的问题的主要原因。)
Thus a fixed version of ReadJson()
would look like: 因此,
ReadJson()
的固定版本看起来像:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jo = JObject.Load(reader);
var typeValue = (string)jo.GetValue("Type", StringComparison.OrdinalIgnoreCase);
Models.CRMIntegrationDirectPromptType integrationPromptType;
if (!Enum.TryParse(typeValue, out integrationPromptType))
{
integrationPromptType = Models.CRMIntegrationDirectPromptType.Label;
}
Models.CreateCRMIntegrationDirectPromptBaseBindingModel model;
switch (integrationPromptType)
{
case Models.CRMIntegrationDirectPromptType.MobilePhone:
model = new Models.CreateCRMIntegrationPromptMobilePhoneBindingModel();
break;
case Models.CRMIntegrationDirectPromptType.Label:
model = new Models.CreateCRMIntegrationPromptLabelBindingModel();
break;
// Add other cases as required.
default:
throw new JsonSerializationException(typeValue);
}
serializer.Populate(jo.CreateReader(), model);
return model;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.