简体   繁体   English

填充对象异常反序列化抽象类时出现意外的初始标记'EndObject'

[英]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;
}

Working sample .Net fiddle here . 工作样本.Net 在这里小提琴。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Twitterizer引发异常:反序列化对象时发生意外的令牌:整数 - Twitterizer throwing an exception: Unexpected token when deserializing object: Integer 使用 YamlDotNet 将 yaml 文件反序列化为抽象 class 的属性时出现异常 - Exception when deserializing yaml file to property of abstract class using YamlDotNet 在JsonConvert.DeserializeObject中反序列化对象时出现意外的标记 - Unexpected token when deserializing object in JsonConvert.DeserializeObject Newtonsoft.Json.JsonSerializationException:'反序列化 object 时出现意外令牌:使用动态 Object 进行评论 - Newtonsoft.Json.JsonSerializationException: 'Unexpected token when deserializing object: Comment with Dynamic Object 反序列化json对象时的异常 - exception when deserializing json object 将 JSON 反序列化为抽象类 - Deserializing JSON to abstract class Twitterizer2 1.2.4 Streaming API 异常 - 反序列化时意外结束 object - Twitterizer2 1.2.4 Streaming API exception - Unexpected end when deserializing object 反序列化对象时读取 DataTable EndArray 时出现意外的 JSON 令牌 - Unexpected JSON token while reading DataTable EndArray While Deserializing Object C# JObject 反序列化多维数组时出现意外标记 - C# JObject Unexpected token when deserializing multidimensional array 使用Json.net反序列化时出现“意外的令牌:StartObject” - “Unexpected token: StartObject” when Deserializing with Json.net
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM