2016-07-16 42 views
10

Tôi đang sử dụng Poison để mã hóa bản đồ thành JSON sẽ gửi nó tới API Slack. Đây là những gì Poison mang lại cho tôi:Mã hóa bản đồ tới JSON bằng cách sử dụng Poison để sử dụng với Slack

"{\"text\":\"changed readme fad996e98e04fd4a861840d92bdcbbcb1e1ec296\"}" 

Khi tôi đặt nó vào JSON lint nó nói đó là JSON hợp lệ, nhưng Slack trả lời "tải trọng không hợp lệ".

Nếu tôi thay đổi JSON để trông như thế này

{"text":"changed readme fad996e98e04fd4a861840d92bdcbbcb1e1ec296"} 

Sau đó nó hoạt động. Có ai biết tôi đang đi sai với cái này không? Tôi có cần phải thực hiện xử lý thêm trên JSON được mã hóa hay không hoặc có một số tiêu đề tôi cần phải đặt không?

Đây là bộ điều khiển của tôi

def create(conn, opts) do 
    message = Message.create_struct(opts) 
    response = Slack.Messages.send(message) 

    case response do 
     {:ok, data} -> 
     render conn, json: Poison.encode!(data) 
     {:error, reason} -> 
     render conn, json: reason 
    end 
end 

Dưới đây là một phần của thư viện để gửi các thông điệp

defmodule Slack.Messages do 

    def format_simple_message(map) do 
    text = map.description <> " " <> map.commits 
    message = %{text: text} 
    end 

    def post_to_slack(map) do 
    Slack.post(:empty, map) 
    end 

    def send(map) do 
    map 
    |> format_simple_message 
    |> post_to_slack 
    end 

end 

Và tôi HTTPoison chế biến

defmodule Slack do 
    use HTTPoison.Base 

    @endpoint "http://url.com" 

    def process_url() do 
    @endpoint 
    end 

    def process_response_body(body) do 
    body 
    |> Poison.decode! # Turns JSON into map 
    end 

    def process_request_body(body) do 
    body 
    |> Poison.encode! # Turns map into JSON 
    end 
end 

Phần tạo ra JSON là trong khối cuối cùng.

+0

Bạn có thể đăng nguồn của chức năng bộ điều khiển có liên quan không? Có thể bạn đang gọi 'json (conn, Poison.encode! (Dữ liệu))' thay vì 'json (conn, data)'. – Dogbert

+0

Đã thêm một số mã để cung cấp ý tưởng tốt hơn về những gì tôi đang làm. – humdinger

+0

"Đây là những gì Poison mang lại cho tôi: ..." ở đâu trong mã bạn đã nhận được giá trị này từ? – Dogbert

Trả lời

2

Dường như tải trọng yêu cầu của bạn được mã hóa JSON hai lần: Lúc đầu, nó trả về chuỗi đầu ra {"text":"..."} và sau đó chuỗi đó được mã hóa lại. JSON có thể không chỉ mã hóa các đối tượng, mà còn các chuỗi để mã hóa ở trên một lần nữa sẽ cung cấp một đầu ra là "{\"text\":\"...\"}". Tức là, một chuỗi chứa biểu diễn được mã hóa JSON của một đối tượng.

Tuy nhiên, API Slack mong đợi một đối tượng có dạng {"text": "..."}, không phải là một chuỗi "...". Cái sau vẫn là JSON hợp lệ, nhưng nó không phải là một yêu cầu hợp lệ cho đến khi API được quan tâm. Đó là lý do tại sao bạn nhận được lỗi "tải trọng không hợp lệ".

Tôi không hoàn toàn chắc chắn là nơi đối tượng được mã hóa lần thứ hai. Mã của bạn ở trên có vẻ ổn, nhưng có thể có các bước xử lý khác không nằm trong các đoạn mã đó. Tôi khuyên bạn nên kiểm tra cẩn thận mã của mình cho một đường dẫn trong đó hai cuộc gọi Poison.encode! được áp dụng cho một số dữ liệu.

Tuy nhiên, có một giải pháp thay thế cho điều này - mặc dù tôi khuyên bạn nên tìm và khắc phục nguyên nhân gốc, mã hóa JSON đôi. Trong process_request_body/1 bạn có thể khớp với đối số - và nếu nó đã là một chuỗi, hãy bỏ qua Poison.encode!. Để làm như vậy, sử dụng đoạn mã sau:

def process_request_body(body) when is_binary(body), do: body 
def process_request_body(body) 
    body 
    |> Poison.encode! # Turns map into JSON 
end 

này sẽ vượt qua chuỗi thông qua đúng nguyên văn và JSON mã hóa bất cứ điều gì khác. Tuy nhiên, điều này có thể nguy hiểm vì một chuỗi vẫn là đầu vào hợp lệ cho mã hóa JSON, vì vậy bạn phải cẩn thận nếu bạn muốn gửi các chuỗi được mã hóa JSON thuần túy qua API. Một lần nữa, tôi khuyên bạn nên sửa chữa nguyên nhân gốc rễ, nhưng tùy thuộc vào tình huống của bạn, cách giải quyết này cũng có thể khả thi.

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