برنامه نویسی

Golang – یک پیام JSON با ویژگی چند نوع را حذف کنید

Summarize this content to 400 words in Persian Lang
Go یک کتابخانه مناسب فراهم می کند که تجزیه پیام JSON را ساده می کند. فقط json.Unmarshal (msg, &parsedStructure) را فراخوانی کنید. این پیام JSON را می گیرد و خصوصیات فردی تعریف شده توسط parsedStructure را تجزیه می کند.

کاملاً کار می کند مگر اینکه خاصیتی داشته باشید که در پیام رفتار خوبی نداشته باشد. به عنوان مثال، در مورد من، پیام یک ایستگاه هواشناسی را می توان در ساختاری به نام WeatherData تجزیه کرد. یک اشکال در تجزیه این است که یک ویژگی در پیام با یک نوع داده منطبق نیست. به طور خاص، مقدار Channel می تواند به صورت یک حرف، به عنوان مثال ‘A’ یا به عنوان یک عدد ظاهر شود. به عنوان مثال، “1”. از آنجایی که json.Unmarshal() از انواع داده های ویژگی های ساختار مقصد برای تعیین نحوه تجزیه پیام استفاده می کند، تنها می تواند یک نوع داده را مدیریت کند.

بنابراین، اگر می‌خواهم نتیجه نهایی پیام تجزیه‌شده شامل یک مقدار رشته برای کانال باشد، تا زمانی که با پیامی با فیلدی مانند این مواجه شود، خوب کار می‌کند: ‘channel: 1’. از آنجایی که انتظار یک مقدار رشته ای برای ‘channel’ در ساختار WeatherData دارد، وقتی عدد ‘1’ را به جای “A” می بیند با شکست مواجه می شود.

چگونه با چنین استثناهایی برخورد کنیم؟ کتابخانه Go JSON شامل یک رابط برای UnmarshalJSON() است که به شما امکان می دهد یک تابع اختصاصی برای رسیدگی به پرونده یک نوع خاص ایجاد کنید. متأسفانه، آن را فقط می توان برای یک ساختار به عنوان یک روش اعمال کرد.

برای اینکه کار کند، ساختار خاصی به نام CustomChannel ایجاد کردم که فقط یک ویژگی دارد، Channel به عنوان یک رشته. سپس، من یک تابع جدید UnmarshalJSON() در اینترفیس نوشتم که نمونه های Channel را به عنوان رشته و Channel را به عنوان int مدیریت می کند. تابع json.Unmarshal () زمانی که به ویژگی Channel می‌رسد، تابع CustomChannel رابط را فراخوانی می‌کند نه اینکه سعی کند آن را صرفاً به عنوان یک رشته تجزیه کند. وقتی تابع UnmarshalJSON سفارشی من برمی گردد، یک عدد صحیح تبدیل شده به رشته را در مورد مقدار int قرار می دهد، یا رشته را در صورتی که در پیام اصلی بود، پس می دهد.

از آنجایی که می‌خواهم با یک مقدار رشته برای Channel کار کنم، یک ساختار مجزا ایجاد کردم، WeatherDataRaw، برای پیام تجزیه‌شده خام با ساختار CustomChannel، و ساختار نهایی WeatherData که در برنامه با آن کار خواهم کرد تا در یک فایل یا یک فایل بنویسم. پایگاه داده

قطعه کد در زیر ساختارها و کد مدیریت پیام نشان داده شده است. می‌توانید ببینید که تابعی که یک پیام را مدیریت می‌کند، json.Unmarshal() را فراخوانی می‌کند، اما سپس تابع رابط فعال می‌شود تا ویژگی CustomChannel را مدیریت کند. یک تابع کمکی مقدار رشته Channel را پس از پردازش از ساختار WeatherDataRaw بازیابی می کند تا بتوان آن را در ساختار WeatherData نهایی ذخیره کرد.

incoming WeatherDataRaw
outgoing WeatherData
)

type WeatherDataRaw struct {
Time string `json:”time”` //”2024-06-11 10:33:52″
Model string `json:”model”` //”Acurite-5n1″
Message_type int `json:”message_type”` //56
Id int `json:”id”` //1997
Channel CustomChannel `json:”channel”` //”A” or 1
Sequence_num int `json:”sequence_num”` //0
Battery_ok int `json:”battery_ok”` //1
Wind_avg_mi_h float64 `json:”wind_avg_mi_h”` //4.73634
Temperature_F float64 `json:”temperature_F”` //69.4
Humidity float64 `json:”humidity”` // Can appear as integer or a decimal value
Mic string `json:”mic”` //”CHECKSUM”
}

type CustomChannel struct {
Channel string
}

func (cc *CustomChannel) channel() string {
return cc.Channel
}

type WeatherData struct {
Time string `json:”time”` //”2024-06-11 10:33:52″
Model string `json:”model”` //”Acurite-5n1″
Message_type int `json:”message_type”` //56
Id int `json:”id”` //1997
Channel string `json:”channel”` //”A” or 1
Sequence_num int `json:”sequence_num”` //0
Battery_ok int `json:”battery_ok”` //1
Wind_avg_mi_h float64 `json:”wind_avg_mi_h”` //4.73634
Temperature_F float64 `json:”temperature_F”` //69.4
Humidity float64 `json:”humidity”` // Can appear as integer or a decimal value
Mic string `json:”mic”` //”CHECKSUM”
}

var messageHandler1 mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
log.Printf(“Received message: %s from topic: %s\n”, msg.Payload(), msg.Topic())
// Sometimes, JSON for channel returns an integer instead of a letter. Check and convert to string.
err := json.Unmarshal(msg.Payload(), &incoming)
if err != nil {
log.Fatalf(“Unable to unmarshal JSON due to %s”, err)
}
copyWDRtoWD()
printWeatherData(outgoing, “home”)
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من مطمئن هستم که ده ها راه دیگر برای رسیدن به این هدف وجود دارد، اما پس از ساعت ها صرف خواندن توضیحات و پست های کتابخانه به صورت آنلاین، این روشی بود که بیشترین حس را برای من داشت.

کد برای پروژه داشبورد آب و هوا که من روی آن کار می کنم در github ارسال شده است. با خیال راحت آن را بررسی کنید و نظر دهید. هنوز در مراحل اولیه است و هنوز رابط کاربری گرافیکی پیاده سازی نشده است، اما این یک پروژه جانبی است که به مرور زمان پیشرفت خواهد کرد.

Go یک کتابخانه مناسب فراهم می کند که تجزیه پیام JSON را ساده می کند. فقط json.Unmarshal (msg, &parsedStructure) را فراخوانی کنید. این پیام JSON را می گیرد و خصوصیات فردی تعریف شده توسط parsedStructure را تجزیه می کند.

کاملاً کار می کند مگر اینکه خاصیتی داشته باشید که در پیام رفتار خوبی نداشته باشد. به عنوان مثال، در مورد من، پیام یک ایستگاه هواشناسی را می توان در ساختاری به نام WeatherData تجزیه کرد. یک اشکال در تجزیه این است که یک ویژگی در پیام با یک نوع داده منطبق نیست. به طور خاص، مقدار Channel می تواند به صورت یک حرف، به عنوان مثال ‘A’ یا به عنوان یک عدد ظاهر شود. به عنوان مثال، “1”. از آنجایی که json.Unmarshal() از انواع داده های ویژگی های ساختار مقصد برای تعیین نحوه تجزیه پیام استفاده می کند، تنها می تواند یک نوع داده را مدیریت کند.

بنابراین، اگر می‌خواهم نتیجه نهایی پیام تجزیه‌شده شامل یک مقدار رشته برای کانال باشد، تا زمانی که با پیامی با فیلدی مانند این مواجه شود، خوب کار می‌کند: ‘channel: 1’. از آنجایی که انتظار یک مقدار رشته ای برای ‘channel’ در ساختار WeatherData دارد، وقتی عدد ‘1’ را به جای “A” می بیند با شکست مواجه می شود.

چگونه با چنین استثناهایی برخورد کنیم؟ کتابخانه Go JSON شامل یک رابط برای UnmarshalJSON() است که به شما امکان می دهد یک تابع اختصاصی برای رسیدگی به پرونده یک نوع خاص ایجاد کنید. متأسفانه، آن را فقط می توان برای یک ساختار به عنوان یک روش اعمال کرد.

برای اینکه کار کند، ساختار خاصی به نام CustomChannel ایجاد کردم که فقط یک ویژگی دارد، Channel به عنوان یک رشته. سپس، من یک تابع جدید UnmarshalJSON() در اینترفیس نوشتم که نمونه های Channel را به عنوان رشته و Channel را به عنوان int مدیریت می کند. تابع json.Unmarshal () زمانی که به ویژگی Channel می‌رسد، تابع CustomChannel رابط را فراخوانی می‌کند نه اینکه سعی کند آن را صرفاً به عنوان یک رشته تجزیه کند. وقتی تابع UnmarshalJSON سفارشی من برمی گردد، یک عدد صحیح تبدیل شده به رشته را در مورد مقدار int قرار می دهد، یا رشته را در صورتی که در پیام اصلی بود، پس می دهد.

از آنجایی که می‌خواهم با یک مقدار رشته برای Channel کار کنم، یک ساختار مجزا ایجاد کردم، WeatherDataRaw، برای پیام تجزیه‌شده خام با ساختار CustomChannel، و ساختار نهایی WeatherData که در برنامه با آن کار خواهم کرد تا در یک فایل یا یک فایل بنویسم. پایگاه داده

قطعه کد در زیر ساختارها و کد مدیریت پیام نشان داده شده است. می‌توانید ببینید که تابعی که یک پیام را مدیریت می‌کند، json.Unmarshal() را فراخوانی می‌کند، اما سپس تابع رابط فعال می‌شود تا ویژگی CustomChannel را مدیریت کند. یک تابع کمکی مقدار رشته Channel را پس از پردازش از ساختار WeatherDataRaw بازیابی می کند تا بتوان آن را در ساختار WeatherData نهایی ذخیره کرد.

    incoming WeatherDataRaw
    outgoing WeatherData
)

type WeatherDataRaw struct {
    Time          string        `json:"time"`          //"2024-06-11 10:33:52"
    Model         string        `json:"model"`         //"Acurite-5n1"
    Message_type  int           `json:"message_type"`  //56
    Id            int           `json:"id"`            //1997
    Channel       CustomChannel `json:"channel"`       //"A" or 1
    Sequence_num  int           `json:"sequence_num"`  //0
    Battery_ok    int           `json:"battery_ok"`    //1
    Wind_avg_mi_h float64       `json:"wind_avg_mi_h"` //4.73634
    Temperature_F float64       `json:"temperature_F"` //69.4
    Humidity      float64       `json:"humidity"`      // Can appear as integer or a decimal value
    Mic           string        `json:"mic"`           //"CHECKSUM"
}

type CustomChannel struct {
    Channel string
}

func (cc *CustomChannel) channel() string {
    return cc.Channel
}

type WeatherData struct {
    Time          string  `json:"time"`          //"2024-06-11 10:33:52"
    Model         string  `json:"model"`         //"Acurite-5n1"
    Message_type  int     `json:"message_type"`  //56
    Id            int     `json:"id"`            //1997
    Channel       string  `json:"channel"`       //"A" or 1
    Sequence_num  int     `json:"sequence_num"`  //0
    Battery_ok    int     `json:"battery_ok"`    //1
    Wind_avg_mi_h float64 `json:"wind_avg_mi_h"` //4.73634
    Temperature_F float64 `json:"temperature_F"` //69.4
    Humidity      float64 `json:"humidity"`      // Can appear as integer or a decimal value
    Mic           string  `json:"mic"`           //"CHECKSUM"
}

var messageHandler1 mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    log.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())
    // Sometimes, JSON for channel returns an integer instead of a letter. Check and convert to string.
    err := json.Unmarshal(msg.Payload(), &incoming)
    if err != nil {
        log.Fatalf("Unable to unmarshal JSON due to %s", err)
    }
    copyWDRtoWD()
    printWeatherData(outgoing, "home")
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من مطمئن هستم که ده ها راه دیگر برای رسیدن به این هدف وجود دارد، اما پس از ساعت ها صرف خواندن توضیحات و پست های کتابخانه به صورت آنلاین، این روشی بود که بیشترین حس را برای من داشت.

کد برای پروژه داشبورد آب و هوا که من روی آن کار می کنم در github ارسال شده است. با خیال راحت آن را بررسی کنید و نظر دهید. هنوز در مراحل اولیه است و هنوز رابط کاربری گرافیکی پیاده سازی نشده است، اما این یک پروژه جانبی است که به مرور زمان پیشرفت خواهد کرد.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا