2016-10-27 7 views
1

ProductStoreモデルを参照しています。 /stores/1というレスポンスで、参照元の製品もあるJSONを返品したいと思います。次のようなものがあります:Json値のリストをHashMapに挿入

{ 
    data: { 
    storeName: "Store1", 
    id: 1 
    products: { 
     { productName : "Product1", productPrice: 10}, 
     { productName : "Product2", productPrice: 100}, 
    } 
    } 
} 

私は現在、適切な場所に注入された製品を得るために私のYesodハンドラにかかっています。

getStoreR :: StoreId -> Handler Value 
getStoreR storeId = do 
    store <- runDB $ get404 storeId 

    products <- runDB $ selectList [StoreId ==. storeId] [] 
    let productsJson = [entityIdToJSON (Entity k r) | Entity k r <- products] 

    let storeJson = entityIdToJSON (Entity storeId store) 

    -- Inject productsJson under "products" property fails 
    let storeJsonWithProducts = HM.insert "products" productsJson storeJson 

    return $ object ["data" .= storeJsonWithProducts] 

はで失敗します。

Couldn't match expected type ‘HM.HashMap k0 [Value]’ 
      with actual type ‘Value’ 
Relevant bindings include 
    storeJsonWithProducts :: HM.HashMap k0 [Value] 
    (bound at Main.hs:80:9) 
In the third argument of ‘HM.insert’, namely ‘storeJson’ 
In the expression: HM.insert "products" productsJson storeJson 

(ところで、私はこのhereを持つ単一のファイル・アプリを作成している)

+1

まず、それぞれの[値]を「ベクトル値」に変換し、それを「配列::ベクトル値 - >値」で「値」に変換する必要があります。次に、ハッシュマップ全体を 'Object :: Map Text Value - > Value'で値に変換します。例えば'オブジェクト。 fmap(Array。fromList) ' – user2407038

+0

あなたの失敗を最小限に抑えてください。基本的に同じエラーが発生するバージョンを作ることができますが、DBバックエンド、yesodの依存関係、ロギング、または任意のコンパイラ拡張を伴わないバージョンを作ることができます。これにより、ここで問題を再現するための努力の閾値が低くなるだけでなく、提案された修正がテストされるだけでなく、問題が皆さんの助けなしに明らかになる可能性が高くなります。完全なエラーも含める必要があります。 –

+0

もちろん、私はそれを最小化しようとします。まだタイプを正しくするのに苦労しています。 – amitaibu

答えて

1

HashMap.insertはタイプk -> v -> HashMap k v -> HashMap k vを持っています。 storeJsonはではなく、コンストラクタで作成されたValueです。これはv ~ Valueを意味します(おなじみでない場合は~をタイプ同値として読むことができます)。ただし、productsJsonValueではありませんが、実際には[Value]であるため、これは問題になります。

したがって、あなたの問題を解決するために、以下を行う必要があります。

  1. storeJsonからHashMapを抽出します。

    let storeHM = case storeJson of 
           Object h -> h 
    

    storeJsonObjectで構成されていない場合は、これがクラッシュするので、あなたは、当然のことながら、適切にここで他のコンストラクタを処理するために確保すべきです。

  2. productJsonからValueに変換してください。 Value年代コンストラクタの一つはArray :: Vector Value -> Valueであり、あなたがData.Vector.fromListを使用して[Value]からVector Valueを取得することができます。

    import qualified Data.Vector as V 
    [...] 
    let productsValue = Array (V.fromList productsJson) 
    
  3. 最後に、storeHMHashMapproductsValueを挿入します。

    let storeHMWithProducts = HM.insert "products" productsValue storeHM 
    

ます。次に進むことができますその場合はobjectを使用してstoreHMWithProductsをJSONに変換してください再び0:

return $ object ["data" .= storeHMWithProducts] 
+0

完璧に動作します。一歩一歩説明していただきありがとうございます。私は実際に次回にどのようにそれを行うのか知っていると思います! – amitaibu

関連する問題