@@ -181,6 +181,31 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
181
181
return buf .Bytes (), nil
182
182
}
183
183
184
+ // MarshalWithOpts is like Marshal but applies custom Marshalling, including data masking and indentation to format the output.
185
+ // The Opts interface specifies methods to control:
186
+ // - Output prefix and indentation options
187
+ // - Omitting empty values (e.g. empty strings)
188
+ // - Custom data masking to have fine-grained control over which specific fields are omitted during serialization.
189
+ // Each JSON element in the output will begin on a new line beginning with prefix
190
+ // followed by one or more copies of indent according to the indentation nesting.
191
+ func MarshalWithOpts (v interface {}, opts Opts ) ([]byte , error ) {
192
+ e := & encodeState {}
193
+ err := e .marshal (v , encOpts {escapeHTML : true , optx : opts })
194
+ if err != nil {
195
+ return nil , err
196
+ }
197
+ if opts .Indent () != "" {
198
+ var buf bytes.Buffer
199
+ err = Indent (& buf , e .Bytes (), opts .Prefix (), opts .Indent ())
200
+ if err != nil {
201
+ return nil , err
202
+ }
203
+ return buf .Bytes (), nil
204
+ } else {
205
+ return e .Bytes (), nil
206
+ }
207
+ }
208
+
184
209
// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
185
210
// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
186
211
// so that the JSON will be safe to embed inside HTML <script> tags.
@@ -260,6 +285,13 @@ type MarshalerError struct {
260
285
Err error
261
286
}
262
287
288
+ type Opts interface {
289
+ OmitEmpty () bool // Exclude fields that have empty values.
290
+ Omit (s reflect.Value , f string ) bool // Return true if field 'f' of struct value 's' should be omitted.
291
+ Prefix () string // Each JSON element in the output will begin on a new line beginning with this prefix
292
+ Indent () string // The indentation string.
293
+ }
294
+
263
295
func (e * MarshalerError ) Error () string {
264
296
return "json: error calling MarshalJSON for type " + e .Type .String () + ": " + e .Err .Error ()
265
297
}
@@ -330,6 +362,8 @@ type encOpts struct {
330
362
quoted bool
331
363
// escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
332
364
escapeHTML bool
365
+ // Omit empty
366
+ optx Opts
333
367
}
334
368
335
369
type encoderFunc func (e * encodeState , v reflect.Value , opts encOpts )
@@ -620,12 +654,17 @@ type structEncoder struct {
620
654
fieldEncs []encoderFunc
621
655
}
622
656
657
+ func (se * structEncoder ) omitField (v reflect.Value , fv reflect.Value , f field , opts encOpts ) bool {
658
+ return ((f .omitEmpty || (opts .optx != nil && opts .optx .OmitEmpty ())) && isEmptyValue (fv )) ||
659
+ (opts .optx != nil && opts .optx .Omit (v , f .name ))
660
+ }
661
+
623
662
func (se * structEncoder ) encode (e * encodeState , v reflect.Value , opts encOpts ) {
624
663
e .WriteByte ('{' )
625
664
first := true
626
665
for i , f := range se .fields {
627
666
fv := fieldByIndex (v , f .index )
628
- if ! fv .IsValid () || f . omitEmpty && isEmptyValue ( fv ) {
667
+ if ! fv .IsValid () || se . omitField ( v , fv , f , opts ) {
629
668
continue
630
669
}
631
670
if first {
0 commit comments