ServiceStack JSON 类型定义应以“”开头

Posted

技术标签:

【中文标题】ServiceStack JSON 类型定义应以“”开头【英文标题】:ServiceStack JSON Type definitions should start with a ''ServiceStack JSON 类型定义应以“”开头 【发布时间】:2013-06-28 06:22:58 【问题描述】:

我有一张桌子

abstract public class TableDefault
    
        [Index(Unique = true)]
        [Alias("rec_version")]
        [Default(typeof(int), "nextval('rec_version_seq')")]
        [Required]
        public int Rec_Version  get; set; 

        [Index(Unique = true)]
        [Alias("rec_id")]
        [Default(typeof(int), "nextval('rec_id_seq')")]
        [Required]
        public int Rec_Id  get; set; 

        [Default(typeof(DateTime), "now()")]
        [Alias("rec_created")]
        [Required]
        public DateTime Rec_Create  get; set; 

        [References(typeof(UserAuth))]
        [Alias("rec_created_id")]
        [Required]
        public int Rec_Created_Id  get; set; 

        [Default(typeof(string), "'1'")]
        [Required]
        [StringLength(1)]
        public string Status  get; set; 

        [Default(typeof(DateTime), "now()")]
        [Alias("rec_modified")]
        [Required]
        public DateTime Rec_Modified  get; set; 

        [References(typeof(UserAuth))]
        [Alias("rec_modified_id")]
        [Required]
        public int Rec_Modified_Id  get; set; 
    

还有

[Alias("dmdvcs")]
    public class DmDvcs : TableDefault
    
        [Alias("ma_dvcs")]
        [PrimaryKey]
        [Default(typeof(string), "''")]
        public string Ma_Dvcs  get; set; 

        [Required]
        [Default(typeof(string), "''")]
        [Alias("ten_dvcs")]
        public string Ten_Dvcs  get; set; 
    

这是我的服务堆栈

[Route("/dmdvcs/Rec_Id/Rec_Version/ten_dvcs/Ten_Dvcs", "PUT")]
    public class Update_DmDvcs_Ten : IReturn<DmDvcs>
    
        public string Ten_Dvcs  get; set; 
        public int Rec_Version  get; set; 
        public int Rec_Id  get; set; 
    
public object Put(Update_DmDvcs_Ten request)
        
            if (string.IsNullOrEmpty(request.Ten_Dvcs))
                throw new ArgumentNullException("Ten_Dvcs");
            if (request.Rec_Id == null)
                throw new ArgumentNullException("Rec_Id");
            if (request.Rec_Version == null)
                throw new ArgumentNullException("Rec_Version");

            var eXistsRow = Db.Select<DmDvcs>(q => q.Rec_Id == request.Rec_Id);
            if (eXistsRow.Count == 0)
                throw HttpError.NotFound("Row 0 does not exist".Fmt(request.Rec_Id));
            else if (eXistsRow.First().Rec_Version != request.Rec_Version)
                throw HttpError.NotFound("Row 0 need update".Fmt(request.Rec_Id));

            IAuthSession session = this.GetSession();
            int rec_version_seq = Db.GetScalar<int>("SELECT nextval('rec_version_seq')");

            DmDvcs updateRow = new DmDvcs
            
                Ten_Dvcs = request.Ten_Dvcs,
                Rec_Modified = DateTime.Now,
                Rec_Modified_Id = session.UserAuthId.ToInt(0),
                Rec_Version = rec_version_seq
            ;

            Db.UpdateOnly(updateRow, 
                ev => ev.Update(c => new  c.Ten_Dvcs, c.Rec_Modified, c.Rec_Modified_Id, c.Rec_Version )
                    .Where(p => p.Rec_Id == request.Rec_Id));

            var newRec = Db.Select<DmDvcs>(p => p.Rec_Id == request.Rec_Id);
            return newRec;
        

在 REST 控制台上:

http://localhost:9998/dmdvcs/8479/8498/ten_dvcs/TestName

返回

[
    "Ma_Dvcs": "DEMO.000",
    "Ten_Dvcs": "TestName",
    "Rec_Version": 8499,
    "Rec_Id": 8479,
    "Rec_Create": "2013-07-01T13:35:02.5430000",
    "Rec_Created_Id": 1,
    "Status": "1",
    "Rec_Modified": "2013-07-01T13:42:37.6910000",
    "Rec_Modified_Id": 1
]

但在 Visual Studio 测试中

[TestMethod]
        public void DmDvcs_update_dvcs_ten()
        
            try
            
                var client = (ServiceClientBase)GetClientWithUserPassword();
                client.AlwaysSendBasicAuthHeader = true;

                DmDvcs getRow = client.Get(new Get_All_Dvcs())[0];

                DmDvcs response = client.Put(new Update_DmDvcs_Ten  Rec_Version = getRow.Rec_Version, Rec_Id = getRow.Rec_Id, Ten_Dvcs = getRow.Ten_Dvcs );

                Assert.AreNotEqual(response, null);
            
            catch (WebServiceException webEx)
            
                Assert.Fail(webEx.Message);
            
        

有错误

System.Runtime.Serialization.SerializationException was unhandled by user code
  HResult=-2146233076
  Message=Type definitions should start with a '', expecting serialized type 'DmDvcs', got string starting with: ["Ma_Dvcs":"DEMO.HNO","Ten_Dvcs":"34234","Rec_Ver
  Source=ServiceStack.Text
  StackTrace:
       at ServiceStack.Text.Common.DeserializeTypeRefJson.StringToType(Type type, String strType, EmptyCtorDelegate ctorFn, Dictionary`2 typeAccessorMap)
       at ServiceStack.Text.Common.DeserializeType`1.<>c__DisplayClass3.<GetParseMethod>b__1(String value)
       at ServiceStack.Text.Json.JsonReader`1.Parse(String value)
       at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value)
       at ServiceStack.Text.JsonSerializer.DeserializeFromStream[T](Stream stream)
       at ServiceStack.ServiceModel.Serialization.JsonDataContractDeserializer.DeserializeFromStream[T](Stream stream)
       at ServiceStack.ServiceClient.Web.JsonServiceClient.DeserializeFromStream[T](Stream stream)
       at ServiceStack.ServiceClient.Web.ServiceClientBase.HandleResponse[TResponse](WebResponse webResponse)
       at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
       at ServiceStack.ServiceClient.Web.ServiceClientBase.Put[TResponse](IReturn`1 request)
       at TSNext.Service.Tests.DmDvcsTests.DmDvcs_update_dvcs_ten() in z:\future13\api\3SNext.Service.Tests\DmDvcsTests.cs:line 170
  InnerException: 

我的 ServiceStack 会发生什么。 我正在使用 ServiceStack 3.9.54 和 PostgreSQL 9.2

【问题讨论】:

【参考方案1】:

此错误通常表明 JSON 有效负载与您尝试反序列化的模型的形状不匹配。

在您的请求 DTO 中,它说此服务将返回 DmDvcs POCO:

public class Update_DmDvcs_Ten : IReturn<DmDvcs>  ... 

但您返回的是 List&lt;DmDvcs&gt;

public object Put(Update_DmDvcs_Ten request)

    ...
    var newRec = Db.Select<DmDvcs>(p => p.Rec_Id == request.Rec_Id);
    return newRec;

这就是你的 JSON 看起来像这样的原因:

[ "Ma_Dvcs": "DEMO.000",.. ]

而不是它所期望的单个 DmDvcs 对象,即:

"Ma_Dvcs": "DEMO.000",..

为了防止以后发生这种情况,我建议指定返回类型,使其与您的 IReturn&lt;T&gt; 响应标记匹配,并且如果您没有返回预期的内容,则会显示类型错误。

public List<DmDvcs> Put(Update_DmDvcs_Ten request)  ... 

【讨论】:

以上是关于ServiceStack JSON 类型定义应以“”开头的主要内容,如果未能解决你的问题,请参考以下文章

解析 ServiceStack 服务并定义内容类型

ServiceStack DateTime数据类型转Json出现的困扰

使用 ServiceStack 自定义 Json 枚举序列化

ServiceStack 文本设置以在反序列化 json 时推断原始值类型

让 ServiceStack 保留类型信息

如何让 ServiceStack 序列化/反序列化具有正确类型的 expando 对象