Search code examples
jsonerlangtsung

Erlang - checking for existence of dynamic variable retrieved from JSON path


I am trying to retrieve an attribute 'seriesId' from a JSON response. This attribute itself may or may not exist in the response.

<dyn_variable name="myseriesId" jsonpath="catalog[0].dummy[0].seriesId"/>      

So, here I want to do some stuff based on the availability of the above attribute. Below is the code that I tried.

<setdynvars sourcetype="eval"
     code="fun({Pid,DynVars})->
            case ts_dynvars:lookup(myseriesId,DynVars) of
                {ok, SeriesId} ->
                      io:format(' seriesId : ~B : ~n',[SeriesId]),
                       BoolSeries = 1;
                 _ ->
                      io:format(' setting bool to zero: ~n'),
                      BoolSeries =0
                 end,
                 BoolSeries
             end.">
         <var name="checkSeries" />
     </setdynvars>

I encountered some issues here. I see this in logs.

 ts_search:(4:<0.102.0>) Dyn Var: no Match (varname=myseriesId),
 ts_client:(5:<0.102.0>) Stop in state wait_ack, reason= {badarg,
                                                          [{io,
                                                          format,
                                                          [<0.77.0>,
                                                          ' seriesId : ~B : ~n',
                                                            [<<>>]],
                                                            []},
                                                            {erl_eval,
                                                            .....

JSON response did not have 'seriesId' attribute, but looks like this code is still hitting 'ok' case. I am confused here. This code works if JSON response has 'seriesId' attribute.

Thanks for any help!


Solution

  • From the log message we can see that the return value of ts_dynvars:lookup(myseriesId,DynVars) is <<>>, i.e. an empty binary, but you expect it to be an integer (to match the ~B format specifier).

    One thing you could do is adding a guard to the case clause, to make sure it only gets selected if the value is an integer:

            case ts_dynvars:lookup(myseriesId,DynVars) of
                {ok, SeriesId} when is_integer(SeriesId) ->
                      io:format(' seriesId : ~B : ~n',[SeriesId]),
    ...
    

    Or you could make another case clause for the case of the empty binary, and deal with it separately.

            case ts_dynvars:lookup(myseriesId,DynVars) of
                {ok, <<>>} ->
                      io:format(' setting bool to zero: ~n'),
                      BoolSeries = 0;
                {ok, SeriesId} ->
                      io:format(' seriesId : ~B : ~n',[SeriesId]),
                       BoolSeries = 1;
    ...