public static Object eval(Parameter param, Map<String, Parameter> params) {
    if (!param.isEvaluated()) {
      switch (param.getType()) {
        case STRING:
          return interpolate(param.asStringParam().getValue(), params);
        case STRING_ARRAY:
          return Arrays.stream(param.asStringArrayParam().getValue())
              .map(v -> interpolate(v, params))
              .toArray(String[]::new);
        case STRING_MAP:
          try {
            return param.asStringMapParam().getValue().entrySet().stream()
                .collect(
                    MapHelper.toListMap(
                        e -> interpolate(e.getKey(), params),
                        e -> interpolate(e.getValue(), params)));
          } catch (Exception e) {
            LOG.error(
                "Failed to evaluate literal param: {} due to ",
                param.asStringMapParam().getValue(),
                e);
            throw e;
          }
        default:
          return param.getValue();
      }
    } else {
      return param.getEvaluatedResult();
    }
  }
@Test
  public void testStringInterpolationJsonError() {
    Parameter param = StringParameter.builder().name("test").value("test $invalidMap").build();
    Map<String, Parameter> params = new LinkedHashMap<>();
    params.put(
        "invalidMap",
        MapParameter.builder()
            .evaluatedResult(Collections.singletonMap("key", new Object()))
            .evaluatedTime(123L)
            .build());

    AssertHelper.assertThrows(
        "Throw an error if param cannot be json serialized",
        MaestroInternalError.class,
        "INTERNAL_ERROR - Cannot evaluate [invalidMap] as string due to",
        () -> LiteralEvaluator.eval(param, params));
  }