proxygen
json_patch.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/json_patch.h>
18 
19 namespace {
20 using folly::StringPiece;
21 // JSON patch operation names
22 constexpr StringPiece kOperationTest = "test";
23 constexpr StringPiece kOperationRemove = "remove";
24 constexpr StringPiece kOperationAdd = "add";
25 constexpr StringPiece kOperationReplace = "replace";
26 constexpr StringPiece kOperationMove = "move";
27 constexpr StringPiece kOperationCopy = "copy";
28 // field tags in JSON patch
29 constexpr StringPiece kOpTag = "op";
30 constexpr StringPiece kValueTag = "value";
31 constexpr StringPiece kPathTag = "path";
32 constexpr StringPiece kFromTag = "from";
33 } // namespace
34 
35 namespace folly {
36 
37 // static
39  dynamic const& obj) noexcept {
40  using err_code = parse_error_code;
41 
42  json_patch patch;
43  if (!obj.isArray()) {
45  }
46  for (auto const& elem : obj) {
47  if (!elem.isObject()) {
49  }
50  auto const* op_ptr = elem.get_ptr(kOpTag);
51  if (!op_ptr) {
53  }
54  if (!op_ptr->isString()) {
56  }
57  auto const op_str = op_ptr->asString();
59 
60  // extract 'from' attribute
61  {
62  auto const* from_ptr = elem.get_ptr(kFromTag);
63  if (from_ptr) {
64  if (!from_ptr->isString()) {
66  }
67  auto json_ptr = json_pointer::try_parse(from_ptr->asString());
68  if (!json_ptr.hasValue()) {
69  return makeUnexpected(
71  }
72  op.from = json_ptr.value();
73  }
74  }
75 
76  // extract 'path' attribute
77  {
78  auto const* path_ptr = elem.get_ptr(kPathTag);
79  if (!path_ptr) {
81  }
82  if (!path_ptr->isString()) {
83  return makeUnexpected(
85  }
86  auto const json_ptr = json_pointer::try_parse(path_ptr->asString());
87  if (!json_ptr.hasValue()) {
88  return makeUnexpected(
90  }
91  op.path = json_ptr.value();
92  }
93 
94  // extract 'value' attribute
95  {
96  auto const* val_ptr = elem.get_ptr(kValueTag);
97  if (val_ptr) {
98  op.value = *val_ptr;
99  }
100  }
101 
102  // check mandatory attributes - different per operation
103  // NOTE: per RFC, the surplus attributes (e.g. 'from' with 'add')
104  // should be simply ignored
105 
107 
108  if (op_str == kOperationTest) {
109  if (!op.value) {
111  }
112  op.op_code = op_code::test;
113  } else if (op_str == kOperationRemove) {
115  } else if (op_str == kOperationAdd) {
116  if (!op.value) {
118  }
119  op.op_code = op_code::add;
120  } else if (op_str == kOperationReplace) {
121  if (!op.value) {
123  }
125  } else if (op_str == kOperationMove) {
126  if (!op.from) {
128  }
129  // is from a proper prefix to path?
130  if (op.from->is_prefix_of(op.path)) {
131  return makeUnexpected(
133  }
134  op.op_code = op_code::move;
135  } else if (op_str == kOperationCopy) {
136  if (!op.from) {
138  }
139  op.op_code = op_code::copy;
140  }
141 
142  if (op.op_code != op_code::invalid) {
143  patch.ops_.emplace_back(std::move(op));
144  } else {
146  }
147  }
148  return patch;
149 }
150 
151 std::vector<json_patch::patch_operation> const& json_patch::ops() const {
152  return ops_;
153 }
154 
155 } // namespace folly
static Expected< json_pointer, parse_error > try_parse(StringPiece const str)
Optional< json_pointer > from
Definition: json_patch.h:77
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
static folly::Expected< json_patch, parse_error > try_parse(dynamic const &obj) noexcept
Definition: json_patch.cpp:38
patch_operation_code op_code
Definition: json_patch.h:75
std::vector< patch_operation > ops_
Definition: json_patch.h:101
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
Definition: Expected.h:785
std::vector< patch_operation > const & ops() const
Definition: json_patch.cpp:151
Range< const char * > StringPiece