1

当使用 Json.NET 将 MVC 视图模型序列化为 json 时,我的视图模型 ( public object Result { get; set;}) 上有一个通用对象属性,它被序列化为键值对而不是实际的 json 对象。有没有我可以用来强制它正确序列化的转换器?

这是 Json.NET 当前正在输出的内容:

"result": [
    {
      "key": "AssetId",
      "value": "b8d8fb71-2553-485b-91bf-14c6c563d78b"
    },
    {
      "key": "SearchResultType",
      "value": "Assets"
    },
    {
      "key": "Name",
      "value": "abstract-q-c-1920-1920-8"
    }
  ]

相反,我希望它输出这个:

"result": {
    "AssetId": "b8d8fb71-2553-485b-91bf-14c6c563d78b",
    "SearchResultType": "Assets",
    "Name": "abstract-q-c-1920-1920-8"
  }

编辑:要回答如何填充该属性的问题,它是通过 RavenDB 索引:

public class SiteSearchIndexTask : AbstractMultiMapIndexCreationTask<SiteSearchResult>
{
    public class Result
    {
        public object[] Content { get; set; }
    }

    public override string IndexName
    {
        get
        {
            return "SiteSearch/All";
        }
    }
    public SiteSearchIndexTask()
    {
        AddMap<Asset>(items => from item in items
                                where item.IsDeleted == false
                               select new 
                                          {
                                              Id = item.Id.ToString(),
                                              ObjectId = item.Id,
                                              ResultType = SearchResultType.Assets,
                                              Title = item.Name.Boost(3),
                                              Tags = item.Tags.Select(x => x.Name).Boost(2),
                                              Result = (object)item,
                                              Query = string.Join(" ", item.Description)
                                          });
        AddMap<User>(items => from item in items
                              where item.IsDeleted == false
                              select new 
                                         {
                                             Id = item.Id,
                                             ObjectId = item.UserId,
                                             ResultType = SearchResultType.Users,
                                             Title = item.Username.Boost(3),
                                             Tags = (BoostedValue) null,
                                             Result = (object)item,
                                             Query = string.Join(" ", item.FullName, item.Email)
                                         });
        Store(x => x.ObjectId, FieldStorage.Yes);
        Store(x => x.ResultType, FieldStorage.Yes);
        Store(x => x.Title, FieldStorage.Yes);
        Store(x => x.Tags, FieldStorage.Yes);
        Store(x => x.Result, FieldStorage.Yes);
        Store(x => x.Query, FieldStorage.Yes);
    }
}

编辑 2 这里是 Asset 和 User 模型(为简洁起见被截断,因为它们只是一堆自动属性)

public class Asset : IHasId
{
    public string Id { get; set; }
    public Guid AssetId
    {
        get
        {
            Guid assetId;
            Guid.TryParse((Id ?? string.Empty).Replace("assets/", ""), out assetId);
            return assetId;
        }
        set { Id = "assets/" + value; }
    }

    public string Name { get; set; }
    public string Description { get; set; }
}

public class User : IHasId
{
    public User()
    {
        Status = UserStatus.Active;
    }

    public string Id { get; set; }
    public int UserId
    {
        get
        {
            int userId;
            int.TryParse((Id ?? string.Empty).Replace("users/", ""), out userId);
            return userId;
        }
        set { Id = "users/" + value; }
    }

    public string Username { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public UserStatus Status { get; set; }
}

编辑 3 事实证明,当我单步执行代码时,该对象实际上是 Raven.Abstractions.Linq.DynamicJsonObject 类型,其中包含一个键值对数组。所以我想这个问题可能比 Json.NET 与 Raven 更相关。除非当然有一个转换器可以从键值对转换为 json 对象。

4

1 回答 1

1

这将有助于了解您是如何准确查询的,但您应该查看在RavenDB 站点上使用多图索引查询不同文档的示例。

当我查看您的索引时,您似乎在字段存储和结果封装方面做得太多。有时很难掌握,但索引中所做的映射不是定义如何返回结果,而是定义索引是如何构建的。除非您正在执行 Reduce 或 TransformResults 步骤,否则您仍会返回原始文档。

因此,将文档封装Result = (object)item为矫枉过正。有一个 ResultType 枚举也是如此。如果您需要知道匹配的文档类型,只需.GetType()在对象上使用,您将很快看到它是用户还是资产。

以下是我将如何定义您的搜索索引。请注意,存在一些差异,因为您在索引中显示的属性不在您提供的模型中。(我假设后端有一个单独的实体而不是前端的模型,但根据需要进行调整。)

public class SearchIndex : AbstractMultiMapIndexCreationTask<SearchIndex.Result>
{
  public class Result
  {
      public object[] Content { get; set; }
      public string ResultType { get; set; }
  }

  public SearchIndex()
  {
      AddMap<Asset>(items => from item in items
                             select new Result
                             {
                               Content = new object[] {item.Name, item.Description},
                               ResultType = MetadataFor(item)["Raven-Entity-Name"].ToString()
                             });

      AddMap<User>(items => from item in items
                            select new Result
                            {
                              Content = new object[] { item.Username, item.FirstName, item.LastName, item.Email },
                              ResultType = MetadataFor(item)["Raven-Entity-Name"].ToString()
                            });

      Index(x => x.Content, FieldIndexing.Analyzed);
    }
}

然后我会像这样查询它:

var results = session.Advanced
                     .LuceneQuery<object, SearchIndex>()
                     .Where("ResultType:" + resultTypeName)
                     .AndAlso()
                     .Search("Content", searchTerm);

然后,您可以简单地检查您的结果,并发现当 cast asobject时,您确实可以执行result.GetType()并查看该对象是如何构造的。如果需要,您还可以在实体上放置一个通用接口来代替对象,例如IAmSearchableRaven 示例中所示。

当您最终通过 MVC 将结果传回时,它应该被正确序列化,因为它将来自真实对象而不是 raven DynamicJsonObject。

于 2012-10-08T16:19:56.633 回答