2015-06-15 63 views
9

Tuyên bố từ chối: Tôi đã kiểm tra câu hỏi here và nó không trả lời câu hỏi của tôi.Elixir - Phân tích cú pháp JSON lồng nhau đến cấu trúc

Tôi đang cố gắng tìm ra cách để phân tích cú pháp cấu trúc lồng nhau của JSON. Ví dụ:

{"name": "blah blah", "address": {"street": "smthing"}} 

Tôi muốn tiếp cận kết quả này:

%User{name: "blah blah", address: %Address{street: "smthing"}} 

Bởi vì sau đó nó sẽ được dễ dàng hơn để cắm xác nhận (sử dụng Vex cho exapmle).

Tôi biết rằng Poison hỗ trợ tùy chọn "dưới dạng cấu trúc" nhưng nó không cung cấp lồng nhau. Ở trên sẽ được phân tích:

%User{name: "blah blah", address: %{"street" => "smthing"}}. 

Tôi biết tôi có thể viết một thực hiện giải mã cho module User nhưng tôi đoán đó không phải là trường hợp mục đích sử dụng và nó sẽ không được chung chung.

Khi tự hỏi về việc triển khai, tôi không thể tìm cách để biết nguyên tử là một mô-đun ... có lẽ tôi phải đi với :code.is_loaded(module_name)?

Dù sao, trước khi thử triển khai, tôi muốn biết nếu có điều gì đó tôi không nhìn thấy.

Trả lời

9

Tôi tin rằng ở trên là bây giờ có thể với Poison:

defmodule User do 
    @derive [Poison.Encoder] 
    defstruct [:address] 
end 

defmodule Address do 
    @derive [Poison.Encoder] 
    defstruct [:street] 
end 

Poison.decode(response, as: %User{address: %Address{}}) 
+1

Điều này rất hữu ích đối với tôi với Poison 2.0. Cảm ơn @Maikon – q231950

5

Hiện tại, tùy chọn duy nhất mà tôi biết là cung cấp triển khai của riêng bạn cho giao thức Poison.Decoder (lưu ý giao thức sau r). Điều này có thêm lợi ích mà bạn có thể có các chuyển đổi này ở một nơi và chỉ cần viết as: User để chuyển địa chỉ được chuyển đổi đúng cách. Ví dụ:

defimpl Poison.Decoder, for: User do 
    def decode(task_list, options) do 
    Map.update! task_list, :address, fn address -> 
     Poison.Decode.decode(address, Keyword.merge(options, as: [Address])) 
    end 
    end 
end 

Lưu ý rằng các cuộc gọi nội để decode không phải là từ Poison.Decoder, nhưng Poison.Decode, mà không có sự trailing r vào tên module. Bạn sẽ không nhận được một lỗi nếu bạn sử dụng sai, nó sẽ không hoạt động, mà có thể là một nỗi đau để gỡ lỗi.

Về lâu dài, tôi nghĩ rằng một chút công việc cần phải được thực hiện trong Poison để làm cho tất cả những điều này thú vị hơn để sử dụng. Có lẽ macro sẽ giúp bạn dễ dàng viết các triển khai Poison.Decoder cho các cấu trúc tùy chỉnh. Có lẽ cũng hỗ trợ cho các tùy chọn cấu trúc lồng nhau như as: %User{address: Address}, điều đó không quá khó để thực hiện. Ngoài ra tôi nghĩ rằng tên mô-đun DecodeDecoder quá dễ nhầm lẫn và một trong số chúng phải được đổi tên. Nếu tôi có thời gian, có lẽ tôi sẽ đưa ra những gợi ý đó và thiết lập một PR với Poison.

+0

Nếu tôi đi theo cách đó có thể là một cách tiếp cận chung chung hơn là để thực hiện một bộ giải mã generic rằng tôi sẽ 'sử dụng BaseDecoder' và sau đó bên trong' def __using __ (_), làm: etc' để xác định một thực hiện cho giao thức. Nhưng sau đó tôi sẽ phải biết nếu một nguyên tử là một mô-đun hợp lệ đó là một cấu trúc. – Olinasc

+0

Cá nhân tôi nghĩ rằng đó là một chút quá nhiều phép thuật, nhưng hey, tại sao không ;-) Chắc chắn thiết lập này có thể được đơn giản hóa, nhưng tôi muốn một cách tiếp cận rõ ràng hơn. Tôi đã mở một vấn đề Github cho điều này, chúng ta hãy xem những gì tác giả ban đầu nghĩ và sau đó có lẽ tôi sẽ cố gắng thực hiện nó. https://github.com/devinus/poison/issues/35 –

Các vấn đề liên quan