2012-10-08 65 views
1

當使用Json.NET序列化MVC視圖模型爲JSON,我有一個通用的對象屬性上,這是獲得序列化到鍵值對,而不是一個我的視圖模型(public object Result { get; set;})實際的json對象。有沒有可以用來強制它正確序列化的轉換器?JsonConverter:序列C#對象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

你能展示你如何填充這個屬性?我想你已經通過了一些字典。你爲什麼不使用匿名對象? –

+0

我編輯了這個問題來展示它是如何完成的。它通過RavenDB索引。 – jwynveen

+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()並查看該對象是如何構建的。如果需要的話,你也可以把你的實體的通用接口轉換爲替代物,如烏鴉例所示的IAmSearchable

當你終於通過您的結果返回通過MVC,應該正確序列化,因爲它會根據現實對象,而不是烏鴉DynamicJsonObject到來。

+0

我這樣做的原因是因爲我也在ResultType屬性上有一個方面,因此用戶可以根據需要過濾到特定的類型。 至於我如何查詢,我使用.AsProjection (),以便它實際上將結果轉換爲我期望的類型。 – jwynveen

+0

我更新了示例以向您展示處理按結果類型過濾的問題的更好方法。 –

+0

不錯!這看起來更好,我在做什麼。我一直在試圖弄清楚如何完成這一切。用你的例子,我仍然可以在Content數組的各個屬性上使用.Boost()嗎? – jwynveen