Magcodes. WeiChat -- custom mcmcreationconverter: serialization of custom menu of WeChat, magicodes. weichat

Source: Internet
Author: User

Magcodes. WeiChat -- customize CustomCreationConverter to serialize custom menus. magicodes. weichat

The custom menu interface is a troublesome interface. Developers often see the following section of the returned JSON, And the whole person will suffer:

 
{"Menu": {"button": [{"type": "click", "name": "Today's song", "key": "V1001_TODAY_MUSIC ", "sub_button": [] },{ "type": "click", "name": "", "key": "V1001_TODAY_SINGER", "sub_button ": [] },{ "name": "menu", "sub_button": [{"type": "view", "name": "Search", "url ": "http://www.soso.com/", "sub_button": []}, {"type": "view", "name": "video", "url": "http://v.qq.com /", "sub_button": []}, {"type": "click", "name": "like us", "key": "V1001_GOOD", "sub_button ": []}

N types, and each type has different attributes, and sub_button is required! Let's shed tears for a while.

When this problem occurs, the average partner is playing like this:

First, we need to confirm the total attributes, as shown below:

Public class MenuFull_RootButton {public string type {get; set;} public string key {get; set;} public string name {get; set;} public string url {get; set ;} public string media_id {get; set;} public List <MenuFull_RootButton> sub_button {get; set ;}}

Then a bunch of lame objects are obtained. I can't bear it! (Starting to install B)

So I began to smother the header encoding (B cannot be installed )~~~

1. Define interface methods

First, define a simple interface method, which is too complicated for you to understand.

/// <Summary> /// custom menu interface // http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html // </summary> public class MenuApi: ApiBase {const string APIName = "menu "; /// <summary> /// User-Defined menu query interface // https://api.weixin.qq.com/cgi-bin/menu/get? Access_token = ACCESS_TOKEN /// </summary> /// <returns> menu return result </returns> public MenuGetApiResultModel Get () {// obtain the api request url var url = GetAccessApiUrl ("get", APIName); return Get <MenuGetApiResultModel> (url, new MenuButtonsCustomConverter ());}}

It is worth noting that the MenuGetApiResultModel and MenuButtonsCustomConverter depend on the two of them.

Note: ApiBase and Get encapsulation should be ignored temporarily. Get is only used to initiate Get requests and serialize JSON. Its definition is as follows:

/// <Summary> /// GET to submit the request, returns the ApiResult object /// </summary> /// <typeparam name = "T"> ApiResult object </typeparam> /// <param name = "url"> request address </param> /// <param name = "jsonConverts"> Json converter </param> /// <returns> ApiResult object </returns> protected T Get <T> (string url, params JsonConverter [] jsonConverts) where T: ApiResult
2. Define the JSON Model

First define the root:

/// <Summary> /// menu return result /// </summary> public class MenuGetApiResultModel: ApiResult {[JsonProperty ("Menu")] public MenuInfo menu {get; set ;}//< summary> /// menu information /// </summary> public class MenuInfo {[JsonProperty ("button")] public List <MenuButtonBase> Button {get; set ;}}

Then define a menu type:

/// <Summary> /// menu type /// </summary> public enum MenuButtonTypes {/// <summary> /// click push event /// </summary> click = 1, /// <summary> /// jump URL /// </summary> view = 2, /// <summary> /// scan the QR code to push events /// </summary> scancode_push = 3, /// <summary> /// scan the QR code to push the event and the message receiving prompt box is displayed. /// </summary> scancode_waitmsg = 4, /// <summary> /// the system screenshot is displayed. /// </summary> pic_sysphoto = 5, /// <summary> /// pop-up photo taking or photo album posting // </summary> pic_photo_or_album = 6, /// <summary> /// the album poster is displayed /// </summary> pic_weixin = 7, /// <summary> /// pop-up location selector /// </summary> location_select = 8, /// <summary> /// send messages (except text messages) /// </summary> media_id = 9, /// <summary> // jump to the URL of the text message /// </summary> view_limited = 10}

Enumeration facilitates maintenance.

Then, you need to define the menu base class and start to base it:

/// <Summary> /// menu button base class /// </summary> public class MenuButtonBase {/// <summary> /// menu title, up to 16 bytes, the sub-menu cannot exceed 40 bytes // </summary> [MaxLength (20)] [JsonProperty (PropertyName = "name", Required = Required. always)] public virtual string Name {get; set ;}/// <summary> // menu type (the type of the menu Response Action) /// </summary> [JsonConverter (typeof (StringEnumConverter)] [JsonProperty (PropertyName = "type")] public MenuButtonTypes Type {get; set ;}}

 

Note: I still like the camel naming method! Therefore, JsonProperty is a good thing. In addition, JsonConverter is used to set the converter. StringEnumConverter is used to convert the string to the corresponding Enumeration type. The MaxLength should be ignored temporarily. I reserve it for future API custom verification. Of course, you can also use it as my preferred one, but we are not doing verification currently, we are doing interface drops.

Okay. Start to get started. Let's first define the level-1 button type. For example, when a sub-menu is included:

/// <Summary> /// sub-menu button /// </summary> public class SubMenuButton: MenuButtonBase {// <summary> // menu title, up to 16 bytes, the sub-menu cannot exceed 40 bytes // </summary> [MaxLength (8)] [JsonProperty (PropertyName = "name", Required = Required. always)] public override string Name {get; set ;}/// <summary> // sub-menu (list menu array, the number should be 1 ~ 5) // </summary> [JsonProperty (PropertyName = "sub_button")] public List <MenuButtonBase> SubButtons {get; set ;}}

 

For other types, the following is an example:

/// <Summary> /// Click the button (click the push event) /// after the user clicks the Click type button, the server pushes the structure of the Message Type as event to the developer (reference message Interface Guide) through the message interface, and carries the key value filled by the developer in the button, developers can interact with users through custom key values; // </summary> public class ClickButton: MenuButtonBase {public ClickButton () {this. type = MenuButtonTypes. click;} // <summary> // menu KEY value, used for message interface push, no more than 128 bytes // </summary> [JsonProperty (PropertyName = "key", Required = Required. always)] public string Key {get; Set ;}//< summary> /// send messages (except text messages) /// after you click the media_id button, the server sends the materials corresponding to the permanent material id entered by the developer to the user. The permanent materials can be images, audios, videos, and text messages. Note: The permanent clip id must be the valid id obtained after the "clip management/Add permanent clip" API is uploaded. /// </Summary> public class MediaIdButton: MenuButtonBase {public MediaIdButton () {this. type = MenuButtonTypes. media_id;} // <summary> // call the valid media_id returned by the new permanent material interface. /// </summary> [JsonProperty (PropertyName = "media_id", Required = Required. always)] public string MediaId {get; set ;}}

One thousand lines of code are omitted below...

Okay, the JSON model has been initially defined. It looks like a decent image! Okay, no more B. Let's continue.

3. Define custom object create converter (CustomCreationConverter )

This B can be installed happily again, so happy.

Let's take a look at its definition:

/// <Summary> /// menu button custom object creation converter /// custom creation based on menu type /// </summary> public class MenuButtonsCustomConverter: customCreationConverter <MenuButtonBase >{/// <summary> /// read the JSON representation of the target object /// </summary> /// <param name = "reader"> JsonReader </param> /// <param name = "objectType"> Object Type </param> /// <param name = "existingValue"> </param> /// <param name = "serializer"> </param> // <returns> Object </returns> public override Object ReadJson (JsonReader, Type objectType, object existingValue, JsonSerializer serializer) {if (reader. tokenType = JsonToken. null) return null; var jObject = JObject. load (reader); MenuButtonBase target = default (MenuButtonBase); // obtain the type attribute var type = jObject. property ("type"); if (type! = Null & type. count> 0) {var typeValue = type. value. toString (); var menuButtonType = (MenuButtonTypes) Enum. parse (typeof (MenuButtonTypes), typeValue); # region returns the corresponding menu type switch (menuButtonType) {case MenuButtonTypes. click: target = new ClickButton (); break; case MenuButtonTypes. view: target = new ViewButton (); break; case MenuButtonTypes. scancode_push: target = new ScancodePushButton (); break; case MenuButtonTypes. scancode_waitmsg: target = new ScancodeWaitmsgButton (); break; case MenuButtonTypes. pic_sysphoto: target = new PicSysphotoButton (); break; case MenuButtonTypes. pic_photo_or_album: target = new PicPhotoOrAlbumButton (); break; case MenuButtonTypes. pic_weixin: target = new PicWeixinButton (); break; case MenuButtonTypes. location_select: target = new LocationSelectButton (); break; case MenuButtonTypes. media_id: target = new MediaIdButton (); break; case MenuButtonTypes. view_limited: target = new ViewLimitedButton (); break; default: throw new NotSupportedException ("menu buttons of this type are not supported:" + menuButtonType );} # endregion} else {target = new SubMenuButton ();} serializer. populate (jObject. createReader (), target); return target ;}/// <summary> // create an object (will be filled) /// </summary> /// <param name = "objectType"> Object Type </param> /// <returns> Object </returns> public override MenuButtonBase Create (type objectType) {return new SubMenuButton ();}}

So far, the entire process is OK. Let's take a look at the results:

This B has finally been installed.

This is the design of MenuApi in Magicodes. WeiChat. Framework. The above section only describes its principles and will improve the personalized menu and related interfaces in the future.

Magicodes. WeiChat. Framework is a lightweight SDK designed by myself. After the Framework is built, this part will be stripped from Magicodes. WeiChat and open-source. We hope you will receive support from enthusiastic audiences.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.