当使用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 以下是资产和用户模型(为简洁而截断,因为它们只是一堆自动属性)
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类型,它包含一组键值对。所以我猜这个问题可能与Raven比Json.NET更相关。除非有一个转换器从键值对转到json对象。
答案 0 :(得分:1)
查看您的查询结果会有所帮助,但您应该查看RavenDB网站上的the example on querying unlike documents with a multimap index。
当我查看您的索引时,您似乎在尝试在字段存储和结果封装方面做得太多。它有时很难掌握,但索引中的映射不是定义结果的返回方式,而是定义索引的构建方式。除非您正在执行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);
然后,您可以简单地检查结果并发现在转换为object
时,您确实可以执行result.GetType()
并查看该对象的构造方式。如果需要,您还可以在实体上放置一个公共接口来强制转换为对象,例如Raven示例中显示的IAmSearchable
。
当你最终通过MVC传回结果时,它应该被正确序列化,因为它将来自真实对象而不是乌鸦DynamicJsonObject。