示例#1
0
Variant HHVM_FUNCTION(json_encode, const Variant& value,
                                   int64_t options /* = 0 */,
                                   int64_t depth /* = 512 */) {
  // Special case for resource since VariableSerializer does not take care of it
  if (value.isResource()) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_UNSUPPORTED_TYPE);

    if (options & k_JSON_PARTIAL_OUTPUT_ON_ERROR) {
      return "null";
    }

    return false;
  }

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
  VariableSerializer vs(VariableSerializer::Type::JSON, options);
  vs.setDepthLimit(depth);

  String json = vs.serializeValue(value, !(options & k_JSON_FB_UNLIMITED));

  if ((json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE) &&
      !(options & k_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
    return false;
  }

  return json;
}
示例#2
0
Variant f_json_decode(const String& json, bool assoc /* = false */,
                      CVarRef options /* = 0 */) {

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

  if (json.empty()) {
    return uninit_null();
  }

  int64_t json_options = options.toInt64();
  if (options.isBoolean() && options.toBooleanVal()) {
    json_options = k_JSON_FB_LOOSE;
  }

  const int64_t supported_options =
    k_JSON_FB_LOOSE | k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS;
  Variant z;
  if (JSON_parser(z, json.data(), json.size(), assoc,
                  (json_options & supported_options))) {
    return z;
  }

  if (json.size() == 4) {
    if (!strcasecmp(json.data(), "null")) return uninit_null();
    if (!strcasecmp(json.data(), "true")) return true;
  } else if (json.size() == 5 && !strcasecmp(json.data(), "false")) {
    return false;
  }

  int64_t p;
  double d;
  DataType type = json->isNumericWithVal(p, d, 0);
  if (type == KindOfInt64) {
    return p;
  } else if (type == KindOfDouble) {
    return d;
  }

  char ch0 = json.charAt(0);
  if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') {
    return json.substr(1, json.size() - 2);
  }

  if ((json_options & k_JSON_FB_LOOSE) && json.size() > 1 &&
      ch0 == '\'' && json.charAt(json.size() - 1) == '\'') {
    return json.substr(1, json.size() - 2);
  }

  if (ch0 == '{' || ch0 == '[') { /* invalid JSON string */
    json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
  }

  assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE);
  return uninit_null();
}
示例#3
0
// Handles output of `json_encode` with fallback value for
// partial output on errors, and `false` otherwise.
Variant json_guard_error_result(const String& partial_error_output,
                                int64_t options /* = 0*/) {
  int is_partial_output = options & k_JSON_PARTIAL_OUTPUT_ON_ERROR;

   // Issue a warning on unsupported type in case of HH syntax.
  if (json_get_last_error_code() ==
      json_error_codes::JSON_ERROR_UNSUPPORTED_TYPE &&
      RuntimeOption::EnableHipHopSyntax) {
    // Unhandled case is always returned as `false`; for partial output
    // we render "null" value.
    raise_warning("json_encode(): type is unsupported, encoded as %s",
      is_partial_output ? "null" : "false");
  }

  if (is_partial_output) {
    return partial_error_output;
  }

  return false;
}
示例#4
0
TypedValue HHVM_FUNCTION(json_encode, const Variant& value,
                         int64_t options, int64_t depth) {
  // Special case for resource since VariableSerializer does not take care of it
  if (value.isResource()) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_UNSUPPORTED_TYPE);
    return tvReturn(json_guard_error_result("null", options));
  }

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
  VariableSerializer vs(VariableSerializer::Type::JSON, options);
  vs.setDepthLimit(depth);

  String json = vs.serializeValue(value, !(options & k_JSON_FB_UNLIMITED));
  assertx(json.get() != nullptr);
  if (UNLIKELY(StructuredLog::coinflip(RuntimeOption::EvalSerDesSampleRate))) {
    StructuredLog::logSerDes("json", "ser", json, value);
  }

  if (json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE) {
    return tvReturn(json_guard_error_result(json, options));
  }

  return tvReturn(std::move(json));
}
示例#5
0
Variant f_json_decode(const String& json, bool assoc /* = false */,
                      CVarRef options /* = 0 */) {

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

  if (json.empty()) {
    return uninit_null();
  }

  int64_t json_options = options.toInt64();
  if (options.isBoolean() && options.toBooleanVal()) {
    json_options = k_JSON_FB_LOOSE;
  }

  const int64_t supported_options =
    k_JSON_FB_LOOSE | k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS;
  int64_t parser_options = json_options & supported_options;
  Variant z;
  if (JSON_parser(z, json.data(), json.size(), assoc, parser_options)) {
    return z;
  }

  if (json.size() == 4) {
    if (!strcasecmp(json.data(), "null")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return uninit_null();
    }
    if (!strcasecmp(json.data(), "true")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return true;
    }
  } else if (json.size() == 5 && !strcasecmp(json.data(), "false")) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return false;
  }

  int64_t p;
  double d;
  DataType type = json->isNumericWithVal(p, d, 0);
  if (type == KindOfInt64) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return p;
  } else if (type == KindOfDouble) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return d;
  }

  char ch0 = json.charAt(0);
  if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

    // Wrap the string in an array to allow the JSON_parser to handle
    // things like unicode escape sequences, then unwrap to get result
    String wrapped("[");
    wrapped += json + "]";
    // Stick to a normal hhvm array for the wrapper
    const int64_t mask = ~(k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS);
    if (JSON_parser(z, wrapped.data(), wrapped.size(), false,
                    parser_options & mask) && z.isArray()) {
      Array arr = z.toArray();
      if ((arr.size() == 1) && arr.exists(0)) {
        return arr[0];
      }
      // The input string could be something like: "foo","bar"
      // Which will parse inside the [] wrapper, but be invalid
      json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
    }
  }

  if ((json_options & k_JSON_FB_LOOSE) && json.size() > 1 &&
      ch0 == '\'' && json.charAt(json.size() - 1) == '\'') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return json.substr(1, json.size() - 2);
  }

  if (ch0 == '{' || ch0 == '[') { /* invalid JSON string */
    json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
  }

  assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE);
  return uninit_null();
}
示例#6
0
int f_json_last_error() {
  return (int) json_get_last_error_code();
}
示例#7
0
int64_t HHVM_FUNCTION(json_last_error) {
  return (int) json_get_last_error_code();
}
示例#8
0
TypedValue HHVM_FUNCTION(json_decode, const String& json,
                         bool assoc, int64_t depth, int64_t options) {
  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

  if (json.empty()) {
    return make_tv<KindOfNull>();
  }

  const int64_t supported_options =
    k_JSON_FB_LOOSE |
    k_JSON_FB_COLLECTIONS |
    k_JSON_FB_STABLE_MAPS |
    k_JSON_BIGINT_AS_STRING |
    k_JSON_FB_HACK_ARRAYS;
  int64_t parser_options = options & supported_options;
  Variant z;
  const auto ok =
    JSON_parser(z, json.data(), json.size(), assoc, depth, parser_options);
  if (UNLIKELY(StructuredLog::coinflip(RuntimeOption::EvalSerDesSampleRate))) {
    StructuredLog::logSerDes("json", "des", json, z);
  }
  if (ok) {
    return tvReturn(std::move(z));
  }

  String trimmed = HHVM_FN(trim)(json, "\t\n\r ");

  if (trimmed.size() == 4) {
    if (!strcasecmp(trimmed.data(), "null")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return make_tv<KindOfNull>();
    }
    if (!strcasecmp(trimmed.data(), "true")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return make_tv<KindOfBoolean>(true);
    }
  } else if (trimmed.size() == 5 && !strcasecmp(trimmed.data(), "false")) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return make_tv<KindOfBoolean>(false);
  }

  int64_t p;
  double d;
  DataType type = json.get()->isNumericWithVal(p, d, 0);
  if (type == KindOfInt64) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return make_tv<KindOfInt64>(p);
  } else if (type == KindOfDouble) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    if ((options & k_JSON_BIGINT_AS_STRING) &&
        (json.toInt64() == LLONG_MAX || json.toInt64() == LLONG_MIN)
        && errno == ERANGE) { // Overflow
      bool is_float = false;
      for (int i = (trimmed[0] == '-' ? 1 : 0); i < trimmed.size(); ++i) {
        if (trimmed[i] < '0' || trimmed[i] > '9') {
          is_float = true;
          break;
        }
      }
      if (!is_float) {
        return tvReturn(trimmed);
      }
    }
    return make_tv<KindOfDouble>(d);
  }

  char ch0 = json.charAt(0);
  if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

    // Wrap the string in an array to allow the JSON_parser to handle
    // things like unicode escape sequences, then unwrap to get result
    String wrapped("[");
    wrapped += json + "]";
    // Stick to a normal hhvm array for the wrapper
    const int64_t mask = ~(k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS);
    if (JSON_parser(z, wrapped.data(), wrapped.size(), false, depth,
                    parser_options & mask) && z.isArray()) {
      Array arr = z.toArray();
      if ((arr.size() == 1) && arr.exists(0)) {
        return tvReturn(arr[0]);
      }
      // The input string could be something like: "foo","bar"
      // Which will parse inside the [] wrapper, but be invalid
      json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
    }
  }

  if ((options & k_JSON_FB_LOOSE) && json.size() > 1 &&
      ch0 == '\'' && json.charAt(json.size() - 1) == '\'') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return tvReturn(json.substr(1, json.size() - 2));
  }

  assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE);
  return make_tv<KindOfNull>();
}
示例#9
0
Variant HHVM_FUNCTION(json_decode, const String& json, bool assoc /* = false */,
                      int64_t depth /* = 512 */, int64_t options /* = 0 */) {

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

  if (json.empty()) {
    return init_null();
  }

  const int64_t supported_options =
    k_JSON_FB_LOOSE |
    k_JSON_FB_COLLECTIONS |
    k_JSON_FB_STABLE_MAPS |
    k_JSON_BIGINT_AS_STRING;
  int64_t parser_options = options & supported_options;
  Variant z;
  if (JSON_parser(z, json.data(), json.size(), assoc, depth, parser_options)) {
    return z;
  }

  String trimmed = f_trim(json, "\t\n\r ");

  if (trimmed.size() == 4) {
    if (!strcasecmp(trimmed.data(), "null")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return init_null();
    }
    if (!strcasecmp(trimmed.data(), "true")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return true;
    }
  } else if (trimmed.size() == 5 && !strcasecmp(trimmed.data(), "false")) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return false;
  }

  int64_t p;
  double d;
  DataType type = json.get()->isNumericWithVal(p, d, 0);
  if (type == KindOfInt64) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return p;
  } else if (type == KindOfDouble) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    if ((options & k_JSON_BIGINT_AS_STRING) &&
        (json.toInt64() == LLONG_MAX || json.toInt64() == LLONG_MIN)
        && errno == ERANGE) { // Overflow
      bool is_float = false;
      for (int i = (trimmed[0] == '-' ? 1 : 0); i < trimmed.size(); ++i) {
        if (trimmed[i] < '0' || trimmed[i] > '9') {
          is_float = true;
          break;
        }
      }
      if (!is_float) {
        return trimmed;
      }
    }
    return d;
  }

  char ch0 = json.charAt(0);
  if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

    // Wrap the string in an array to allow the JSON_parser to handle
    // things like unicode escape sequences, then unwrap to get result
    String wrapped("[");
    wrapped += json + "]";
    // Stick to a normal hhvm array for the wrapper
    const int64_t mask = ~(k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS);
    if (JSON_parser(z, wrapped.data(), wrapped.size(), false, depth,
                    parser_options & mask) && z.isArray()) {
      Array arr = z.toArray();
      if ((arr.size() == 1) && arr.exists(0)) {
        return arr[0];
      }
      // The input string could be something like: "foo","bar"
      // Which will parse inside the [] wrapper, but be invalid
      json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
    }
  }

  if ((options & k_JSON_FB_LOOSE) && json.size() > 1 &&
      ch0 == '\'' && json.charAt(json.size() - 1) == '\'') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return json.substr(1, json.size() - 2);
  }

  assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE);
  return init_null();
}