@@ -62,6 +62,8 @@ type partialDoc struct {
62
62
self * lazyNode
63
63
keys []string
64
64
obj map [string ]* lazyNode
65
+
66
+ opts * ApplyOptions
65
67
}
66
68
67
69
type partialArray struct {
@@ -92,6 +94,8 @@ type ApplyOptions struct {
92
94
// EnsurePathExistsOnAdd instructs json-patch to recursively create the missing parts of path on "add" operation.
93
95
// Default to false.
94
96
EnsurePathExistsOnAdd bool
97
+
98
+ EscapeHTML bool
95
99
}
96
100
97
101
// NewApplyOptions creates a default set of options for calls to ApplyWithOptions.
@@ -101,6 +105,7 @@ func NewApplyOptions() *ApplyOptions {
101
105
AccumulatedCopySizeLimit : AccumulatedCopySizeLimit ,
102
106
AllowMissingPathOnRemove : false ,
103
107
EnsurePathExistsOnAdd : false ,
108
+ EscapeHTML : true ,
104
109
}
105
110
}
106
111
@@ -143,13 +148,21 @@ func (n *partialDoc) TrustMarshalJSON(buf *bytes.Buffer) error {
143
148
if err := buf .WriteByte ('{' ); err != nil {
144
149
return err
145
150
}
151
+ escaped := true
152
+
153
+ // n.opts should always be set, but in case we missed a case,
154
+ // guard.
155
+ if n .opts != nil {
156
+ escaped = n .opts .EscapeHTML
157
+ }
158
+
146
159
for i , k := range n .keys {
147
160
if i > 0 {
148
161
if err := buf .WriteByte (',' ); err != nil {
149
162
return err
150
163
}
151
164
}
152
- key , err := json .Marshal ( k )
165
+ key , err := json .MarshalEscaped ( k , escaped )
153
166
if err != nil {
154
167
return err
155
168
}
@@ -159,7 +172,7 @@ func (n *partialDoc) TrustMarshalJSON(buf *bytes.Buffer) error {
159
172
if err := buf .WriteByte (':' ); err != nil {
160
173
return err
161
174
}
162
- value , err := json .Marshal (n .obj [k ])
175
+ value , err := json .MarshalEscaped (n .obj [k ], escaped )
163
176
if err != nil {
164
177
return err
165
178
}
@@ -200,11 +213,11 @@ func (n *partialArray) RedirectMarshalJSON() (interface{}, error) {
200
213
return n .nodes , nil
201
214
}
202
215
203
- func deepCopy (src * lazyNode ) (* lazyNode , int , error ) {
216
+ func deepCopy (src * lazyNode , options * ApplyOptions ) (* lazyNode , int , error ) {
204
217
if src == nil {
205
218
return nil , 0 , nil
206
219
}
207
- a , err := json .Marshal (src )
220
+ a , err := json .MarshalEscaped (src , options . EscapeHTML )
208
221
if err != nil {
209
222
return nil , 0 , err
210
223
}
@@ -222,7 +235,7 @@ func (n *lazyNode) nextByte() byte {
222
235
return s [0 ]
223
236
}
224
237
225
- func (n * lazyNode ) intoDoc () (* partialDoc , error ) {
238
+ func (n * lazyNode ) intoDoc (options * ApplyOptions ) (* partialDoc , error ) {
226
239
if n .which == eDoc {
227
240
return n .doc , nil
228
241
}
@@ -241,6 +254,7 @@ func (n *lazyNode) intoDoc() (*partialDoc, error) {
241
254
return nil , ErrInvalid
242
255
}
243
256
257
+ n .doc .opts = options
244
258
if err != nil {
245
259
return nil , err
246
260
}
@@ -551,7 +565,7 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
551
565
return nil , ""
552
566
}
553
567
} else {
554
- doc , err = next .intoDoc ()
568
+ doc , err = next .intoDoc (options )
555
569
556
570
if err != nil {
557
571
return nil , ""
@@ -769,6 +783,7 @@ func (p Patch) add(doc *container, op Operation, options *ApplyOptions) error {
769
783
} else {
770
784
pd = & partialDoc {
771
785
self : val ,
786
+ opts : options ,
772
787
}
773
788
}
774
789
@@ -874,7 +889,7 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
874
889
newNode := newLazyNode (newRawMessage (rawJSONObject ))
875
890
876
891
doc .add (part , newNode , options )
877
- doc , err = newNode .intoDoc ()
892
+ doc , err = newNode .intoDoc (options )
878
893
if err != nil {
879
894
return err
880
895
}
@@ -887,7 +902,7 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
887
902
return err
888
903
}
889
904
} else {
890
- doc , err = target .intoDoc ()
905
+ doc , err = target .intoDoc (options )
891
906
892
907
if err != nil {
893
908
return err
@@ -973,6 +988,8 @@ func (p Patch) replace(doc *container, op Operation, options *ApplyOptions) erro
973
988
if ! val .tryAry () {
974
989
return errors .Wrapf (err , "replace operation value must be object or array" )
975
990
}
991
+ } else {
992
+ val .doc .opts = options
976
993
}
977
994
}
978
995
@@ -1134,7 +1151,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64, op
1134
1151
return errors .Wrapf (ErrMissing , "copy operation does not apply: doc is missing destination path: %s" , path )
1135
1152
}
1136
1153
1137
- valCopy , sz , err := deepCopy (val )
1154
+ valCopy , sz , err := deepCopy (val , options )
1138
1155
if err != nil {
1139
1156
return errors .Wrapf (err , "error while performing deep copy" )
1140
1157
}
@@ -1221,6 +1238,7 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
1221
1238
} else {
1222
1239
pd = & partialDoc {
1223
1240
self : self ,
1241
+ opts : options ,
1224
1242
}
1225
1243
}
1226
1244
@@ -1257,11 +1275,18 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
1257
1275
}
1258
1276
}
1259
1277
1260
- if indent != "" {
1261
- return json .MarshalIndent (pd , "" , indent )
1278
+ data , err := json .MarshalEscaped (pd , options .EscapeHTML )
1279
+ if err != nil {
1280
+ return nil , err
1281
+ }
1282
+
1283
+ if indent == "" {
1284
+ return data , nil
1262
1285
}
1263
1286
1264
- return json .Marshal (pd )
1287
+ var buf bytes.Buffer
1288
+ json .Indent (& buf , data , "" , indent )
1289
+ return buf .Bytes (), nil
1265
1290
}
1266
1291
1267
1292
// From http://tools.ietf.org/html/rfc6901#section-4 :
0 commit comments