How to pass raw JSON with spaces and tabs to a struct in Go without extra escaping or marshaling - Stack Overflow

I'm working with a Go application where I need to pass raw JSON data to a struct field, but I am e

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744966712a4603724.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信