What am I doing wrong parsing json?

I am trying to collect state of a switch on other ESPHome device using rest.

Here is the code

        - http_request.get: 
            url: http://esp8266-esp-01.local/switch/relay2
            verify_ssl: false
            on_response:
               then:
                 - logger.log:
                     format: 'Response status: %d'
                     args: [status_code]
                 - lambda: |-
                     const char* httpResponse = id(http_request_data).get_string();
                     ESP_LOGD("http_response", "Response %s", httpResponse);

                     json::parse_json(httpResponse, [](JsonObject root) {
                         ESP_LOGD("http_parse", "id: %s", root["id"]);
                         ESP_LOGD("http_parse", "state: %s", root["state"]);
                    });

Response recevied is OK. This is what response contains:

{"id":"switch-relay2","value":true,"state":"ON"}

It seems as proper json, but parsing goes wrong. I get gibberish.

Here is excerpt from the log my code produces:

[11:15:48][D][main:490]: Get status
[11:15:48][D][main:499]: Response status: 200
[11:15:48][D][http_response:115]: Response {"id":"switch-relay2","value":true,"state":"ON"}
[11:15:48][D][http_parse:118]: id: @
[11:15:48][D][http_parse:119]: state: @
[11:15:48][D][http_request:094]: HTTP Request completed; URL: http://esp8266-esp-01.local/switch/relay2; Code: 200

If state in json is OFF then all values are parsed as ā€œDā€ instead of ā€œ@ā€. While i can play with @ and D to recognize status that is plain wrong. I want to get proper value.

Am I doing something wrong or there is some issue with json::parse_json()?

It seems this is issue of type casting from const char* to string. I tried several methods suggested, but nothing actually worked.

I am not familiar with c++ so I guess there is simple solution, I just cannot get to it.

With help I got on Discord I got this working. Here is example if sokoene else subles on this issue:


select:
  - platform: template
    name: Remote Sensor
    id: remote_sensor
    options: 
     - "OFF"
     - "ON"
    set_action: 
      - lambda: |-
          id(remote_sensor).state = x.c_str();

http_request:
  id: http_request_data
  useragent: esphome/device
  timeout: 10s 
  esp8266_disable_ssl_support: true

interval:
  - interval: 10s
    then:
      - if:
          condition:
            wifi.connected:
          then:      
            - logger.log: "Get status"
            - http_request.get: 
                url: http://esp8266-esp-01.local/switch/relay2
                verify_ssl: false
                on_response:
                  then:
                    - logger.log:
                        format: 'Response status: %d'
                        args: [status_code]
                    - lambda: |-

                        if (status_code == 200) {
                          const char* httpResponse = id(http_request_data).get_string();
                          
                          std::string httpResponseStr = httpResponse;
                          ESP_LOGD("http_response", "Response %s", httpResponseStr.c_str());

                          json::parse_json(httpResponse, [](JsonObject root) {
                            ESP_LOGD("http_parse", "id: %s", std::string(root["id"]).c_str());
                            ESP_LOGD("http_parse", "state: %s", std::string(root["state"]).c_str());
                            id(remote_sensor).state = std::string(root["state"]).c_str();

                            if (root["state"] == "ON") {
                               // do something....
                            }
                          });                          
                         
                        } else {
                          ESP_LOGD("http_response", "Failed connection to remote sensor. Status code: %d", status_code);
                        }
          else:
            - logger.log: "Error: No WiFi"  
   

1 Like

Thanks for sharing it back!