admin管理员组

文章数量:1406048

I'm working with a Go application where I need to pass raw JSON data to a struct field, but I am encountering issues with extra escaping when marshaling the struct, especially when the raw JSON contains spaces and tabs. Specifically, I am using the following structs:

type BrandTemplate struct {
    Type     string `json:"type"`     // Template type (e.g., email_fot_password)
    Locale   string `json:"locale"`   // Locale (e.g., "es" for Spanish, "en" for English)
    Template string `json:"template"` // Template content (Email/SMS content)
}

type BrandTemplate1 struct {
    Type     string          `json:"type"`
    Locale   string          `json:"locale"`
    Template json.RawMessage `json:"template"` // Use RawMessage to avoid extra escaping
}

The BrandTemplate struct expects the Template field to be a string, but the raw JSON I need to pass contains spaces, tabs, and special characters that require escaping, which I don’t want to escape manually.

On the other hand, the BrandTemplate1 struct uses json.RawMessage, which works perfectly because it preserves the raw JSON format. But I want to use the BrandTemplate struct, and I am wondering if there’s a way to avoid manually escaping the JSON string and passing raw JSON in a clean way while preserving the spaces, tabs, and other formatting.

Here’s an example of what I am trying to do:

// Define the template as raw JSON
template := `{
    "subject": "Email MFA App Verification Code",
    "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>",
    "plain": "Here is the code: {{otp_code}}"
}`

// Create a new BrandTemplate object
brandTemplate := models.BrandTemplate{
    Type:     "email_code_app_verification", // Example template type
    Locale:   "en",                          // Locale for the template (English)
    Template: template,                      // Pass the raw JSON string
}

This is the output I am getting when I print brandTemplate:

BrandTemplate JSON:
{
  "type": "email_code_app_verification",
  "locale": "en",
  "template": "{\n\t\t\"subject\": \"Email MFA App Verification Code\",\n\t\t\"html\": \"\\u003chtml\\u003e\\u003chead\\u003e\\u003c/head\\u003e\\u003cbody\\u003e\\u003cp\\u003eHere is the code: {{otp_code}}\\u003c/p\\u003e\\u003c/body\\u003e\\u003c/html\\u003e\",\n\t\t\"plain\": \"Here is the code: {{otp_code}}\"\n\t}"
}

This is the expected output:

BrandTemplate JSON:
{
    "type": "email_code_app_verification",
    "locale": "en",
    "template": {
        "subject": "Email MFA App Verification Code",
        "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>",
        "plain": "Here is the code: {{otp_code}}"
    }
}

Is there a better way to pass raw JSON with spaces and tabs into the BrandTemplate struct without additional escaping or marshaling? I’ve seen json.RawMessage used in other contexts, but I’d like to avoid that if possible and work directly with the BrandTemplate struct as it is.

Any advice or solutions for this would be greatly appreciated!

I'm working with a Go application where I need to pass raw JSON data to a struct field, but I am encountering issues with extra escaping when marshaling the struct, especially when the raw JSON contains spaces and tabs. Specifically, I am using the following structs:

type BrandTemplate struct {
    Type     string `json:"type"`     // Template type (e.g., email_fot_password)
    Locale   string `json:"locale"`   // Locale (e.g., "es" for Spanish, "en" for English)
    Template string `json:"template"` // Template content (Email/SMS content)
}

type BrandTemplate1 struct {
    Type     string          `json:"type"`
    Locale   string          `json:"locale"`
    Template json.RawMessage `json:"template"` // Use RawMessage to avoid extra escaping
}

The BrandTemplate struct expects the Template field to be a string, but the raw JSON I need to pass contains spaces, tabs, and special characters that require escaping, which I don’t want to escape manually.

On the other hand, the BrandTemplate1 struct uses json.RawMessage, which works perfectly because it preserves the raw JSON format. But I want to use the BrandTemplate struct, and I am wondering if there’s a way to avoid manually escaping the JSON string and passing raw JSON in a clean way while preserving the spaces, tabs, and other formatting.

Here’s an example of what I am trying to do:

// Define the template as raw JSON
template := `{
    "subject": "Email MFA App Verification Code",
    "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>",
    "plain": "Here is the code: {{otp_code}}"
}`

// Create a new BrandTemplate object
brandTemplate := models.BrandTemplate{
    Type:     "email_code_app_verification", // Example template type
    Locale:   "en",                          // Locale for the template (English)
    Template: template,                      // Pass the raw JSON string
}

This is the output I am getting when I print brandTemplate:

BrandTemplate JSON:
{
  "type": "email_code_app_verification",
  "locale": "en",
  "template": "{\n\t\t\"subject\": \"Email MFA App Verification Code\",\n\t\t\"html\": \"\\u003chtml\\u003e\\u003chead\\u003e\\u003c/head\\u003e\\u003cbody\\u003e\\u003cp\\u003eHere is the code: {{otp_code}}\\u003c/p\\u003e\\u003c/body\\u003e\\u003c/html\\u003e\",\n\t\t\"plain\": \"Here is the code: {{otp_code}}\"\n\t}"
}

This is the expected output:

BrandTemplate JSON:
{
    "type": "email_code_app_verification",
    "locale": "en",
    "template": {
        "subject": "Email MFA App Verification Code",
        "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>",
        "plain": "Here is the code: {{otp_code}}"
    }
}

Is there a better way to pass raw JSON with spaces and tabs into the BrandTemplate struct without additional escaping or marshaling? I’ve seen json.RawMessage used in other contexts, but I’d like to avoid that if possible and work directly with the BrandTemplate struct as it is.

Any advice or solutions for this would be greatly appreciated!

Share Improve this question edited Mar 7 at 8:31 Basheer Jarrah 6404 silver badges16 bronze badges asked Mar 6 at 15:20 SparshSparsh 13 bronze badges 4
  • 1 This is one of the uses for RawMessage, to store the raw json data in a struct, so why do you want to avoid it? – Mr_Pink Commented Mar 6 at 15:44
  • The answer to your question is a simple No. – Volker Commented Mar 6 at 16:12
  • @Mr_Pink I’m avoiding RawMessage because, according to the documentation, the template type is defined as a String. This might lead to potential inconsistencies when dealing with raw JSON data, and I want to ensure we adhere to the expected data type. – Sparsh Commented Mar 7 at 8:36
  • 1 @Sparsh, RawMessage is just a []byte which can be losslessly converted to and from a string, so there's it's not going to any inconsistent data. This is what you're doing below, except delaying it the point of encoding. However is the types didn't work or you need different output, the answer to any custom encoding question is going to be MarshalJSON and UnmarshalJSON. – Mr_Pink Commented Mar 7 at 13:31
Add a comment  | 

1 Answer 1

Reset to default 0

Convert the Template field to json.RawMessage in a MarshalJSON method on BrandTemplate.

type BrandTemplate struct {
    Type     string `json:"type"`   // Template type (e.g., email_fot_password)
    Locale   string `json:"locale"` // Locale (e.g., "es" for Spanish, "en" for English)
    Template string `json:"-"`      // Template content (Email/SMS content)
}

func (t *BrandTemplate) MarshalJSON() ([]byte, error) {
    // Define type to break recursive calls to MarshalJSON.
    // The type X has all of fields for BrandTemplate, but
    // non of the methods.
    type X BrandTemplate

    // Marshal a type that shadows BrandTemplate.Template
    // with a raw JSON field of the same name.
    return json.Marshal(
        struct {
            *X
            Template json.RawMessage `json:"template"`
        }{
            (*X)(t),
            json.RawMessage(t.Template),
        })
}

https://go.dev/play/p/cG8kPgltwvw

本文标签: