2013-03-30 1 views
2

Я довольно новичок.json-rpc in golang, id as string

Я использую этот пакет https://github.com/kdar/httprpc сделать мой JSON-RPC v 1.0 запросов (как golang реализует только 2,0)

У меня есть проблема, этот сервер я звоню вернуть «идентификатор» в виде строки, как

"id":"345" 

вместо

"id":345 

единственный способ я нашел, чтобы переопределить clientResponse используя строку вместо uint64

type clientResponse struct { 
    Result *json.RawMessage `json:"result"` 
    Error interface{}  `json:"error"` 
    Id  string   `json:"id"` 
} 

и переопределить функцию exacte же DecodeClientResponse использовать мой clientResponse

и вместо CallJson, я называю (DecodeClientResponse вместо gjson.DecodeClientResponse):

httprpc.CallRaw(address, method, &params, &reply, "application/json", 
      gjson.EncodeClientRequest, DecodeClientResponse) 

Я нахожу это довольно некрасиво , есть ли способ сделать лучше?

Благодаря

ответ

2

JSON-RPC v 1.0 определяет, что:

ID - Идентификатор запроса. Это может быть любого типа. Он используется для соответствия ответа с запросом, на который он отвечает.

То есть, id может быть что угодно (даже массив), и ответ сервера должен содержать одинаковое значение и тип идентификатора, который в вашем случае это не делает. Таким образом, сервер, с которым вы общаетесь, не выполняет свою работу правильно и не следует спецификациям json-rpc v 1.0.

Итак, да, вам нужно сделать «уродливое» решение и создать новую функцию декодера для этого «сломанного» сервера. Предложение Джереми Уолла работает (но int должно быть изменено на uint64) и должно по крайней мере заставить вас избегать использования string как типа.

Редактировать

Я не знаю httprpc пакета достаточно, чтобы знать, как он обрабатывает значение Id. Но если вы хотите, либо строку или Int, вы должны быть в состоянии установить Id в clientResponse к:

Id interface{} `json:"id"` 

При проверке значения в Id вы используете тип переключателя:

var id int 
// response is of type clientResponse 
switch t := response.Id.(type) { 
default: 
    // Error. Bad type 
case string: 
    var err error 
    id, err = strconv.Atoi(t) 
    if err != nil { 
     // Error. Not possible to convert string to int 
    } 
case int: 
    id = t 
} 
// id now contains your value 
+0

Спасибо, и это возможно декодировать как int, так и строку, например, если int не работает, попробуйте строку. Или мне нужно: StringId string 'json:" id "' и IntId uint64 'json:" id "'? – vieux

+0

Да, это возможно. Я не знаю пакет 'httprpc', чтобы знать, как он обрабатывает значение id. Но я отредактировал ответ, чтобы показать, как использовать 'interface {}' вместо строки. – ANisus

1

Попробуйте

type clientResponse struct { 
    Result *json.RawMessage `json:"result"` 
    Error interface{}  `json:"error"` 

    # Tell encoding/json that the field is 
    # encoded as a json string even though the type is int. 
    Id  int   `json:"id,string"` 
} 

Пока библиотеки используют кодирование/JSON под капотом это должно работать.