2014-11-06 79 views
7

我想从phoenix中的ecto协会生成JSON。从elixir ecto协会创建json

这是我的联想:

defmodule Blog.Post do 
    use Ecto.Model 

    schema "posts" do 
    field :title, :string 
    field :body, :string 
    has_many :comments, Blog.Comment 
    end 
end 

和:

defmodule Blog.Comment do 
    use Ecto.Model 

    schema "comments" do 
    field :content, :string 
    belongs_to :post, Blog.Post 
    end 
end 

当我产生无关联的JSON的结果是这样的:

[%Blog.Post{body: "this is the very first post ever!", id: 1,title: "first post"}, 
%Blog.Post{body: "Hello nimrod!!!!", id: 12, title: "hi Nimrod"}, 
%Blog.Post{body: "editing the body!!!!", id: 6, title: "hello(edit)"}] 

和JSON看起来像这样

{"posts": [ 
    { 
     "title": "first post", 
     "id": 1, 
     "body": "this is the very first post ever!" 
    }, 
    { 
     "title": "hi Nimrod", 
     "id": 12, 
     "body": "Hello nimrod!!!!" 
    }, 
    { 
     "title": "hello(edit)", 
     "id": 6, 
     "body": "editing the body!!!!" 
    } 
]} 

,但与联想的结果是这样的

[%Blog.Post{body: "this is the very first post ever!", 
comments: {Ecto.Associations.HasMany.Proxy, 
#Ecto.Associations.HasMany<[name: :comments, target: Blog.Post, 
associated: Blog.Comment, references: :id, foreign_key: :post_id]>}, id: 1, 
title: "first post"}, 
%Blog.Post{body: "Hello nimrod!!!!", 
comments: {Ecto.Associations.HasMany.Proxy, 
#Ecto.Associations.HasMany<[name: :comments, target: Blog.Post, 
associated: Blog.Comment, references: :id, foreign_key: :post_id]>}, id: 12, 
title: "hi Nimrod"}, 
%Blog.Post{body: "editing the body!!!!", 
comments: {Ecto.Associations.HasMany.Proxy, 
#Ecto.Associations.HasMany<[name: :comments, target: Blog.Post, 
associated: Blog.Comment, references: :id, foreign_key: :post_id]>}, id: 6, 
title: "hello(edit)"}] 

通过上述输出我不能创建一个合适的JSON输出。我想为json看起来像这样

{"posts": [ 
    { 
     "title": "the title", 
     "id": 1, 
     "body": "the body", 
     "comments": [{"content": "a comment"}, {"content": "another comment"}] 
    } 
    ... 
]} 

任何帮助,将不胜感激。

+0

您使用哪个库来生成JSON?请添加示例代码段。 – 2014-11-07 11:13:54

+0

它是默认的凤凰库,Poison: 'Poison.encode! %{posts:Blog.Repo.all(Blog.Post)}' – idobn 2014-11-07 16:19:53

+0

我假设你得到一个错误,是吗?你可以在这里发布错误吗? – 2014-11-07 18:57:15

回答

6

哎哟,现在还没有简单的解决方案。我会尝试这样的:

defimpl Poison.Encoder, for: Tuple do 
    def encode(proxy, options) do 
    Poison.Encoder.List.to_json(proxy.all, options) 
    end 
end 

我们基本上实现了接收上面的代理和编码所有项目的元组的编码器。我们需要为此讨论更好的解决方案。

+0

我不确定我是否完全理解你在做什么......你可能会展示一个你将如何做的例子。 – idobn 2014-11-10 05:39:11

+1

这是围绕Ecto无法呈现关联的黑客攻击。你应该把它添加到你的项目文件中,它应该是足够的,除非我错过了一些东西,但是上面代码中的代理是'post.comments'返回的值。理性的是,关联代理是一个元组,所以你正在教Poison如何将这些呈现给JSON。 – 2014-11-10 17:31:33

+0

我试着把这个添加到我的项目中,并收到以下警告:'警告:未定义的协议功能编码/ 2(对于协议Poison.Encoder)'并且在我尝试运行'Poison.encode! Blog.Repo.all(Blog.Post)'我收到这个错误:'**(UndefinedFunctionError)未定义的函数:Poison.Encoder.Tuple.encode/2 (博客)Poison.Encoder.Tuple.encode({Ecto.Associations .HasMany.Proxy,#Ecto.Associations.HasMany <[name::comments,target:Blog.Post,associated:Blog.Comment,references::id,foreign_key::post_id]>},[])' – idobn 2014-11-11 16:18:28