C++のJSONラブラリ (JSON for Modern C++)と、JSONのUDPでの運び方
C++でJSONを扱わなければならなくなりました。
blog.livedoor.jp/tek_nishi/archives/10216517.html
に、
JSON for Modern C++ を紹介するよ!ブログに書いた書いたと思い込んでてまったく触れてなかった...このJSON読み書きライブラリは他のライブラリに依存しておらず、json.hppをインクルードするだけというお手軽さながら、JSONオブジェクトをめっちゃ気楽に扱えるようにしてくれます。
なん・・だと・・。インクルードするだけ・・ 採用決定!!
となりました。
で、早速、
$ git clone https://github.com/nlohmann/json.git
をして、
// g++ test_json.cpp -o test_json -I json/include/
// g++ test_json.cpp -o test_json -I json/include/
#include <stdio.h>
#include <string.h>
#include <nlohmann/json.hpp>
#include <iostream>
int main(int argc, char **argv){
using json = nlohmann::json;
json j;
j["pi"] = 3.141;
j["happy"] = true;
j["name"] = "Niels";
j["nothing"] = nullptr;
j["answer"]["everything"] = 42;
j["list"] = { 1, 0, 2 }; // [1,0,2]
j["object"] = { {"currency", "USD"}, {"value", 42.99} }; // {"currentcy": "USD", "value": 42.99}
std::cout << j << std::endl; // cout
return 0;
}
をした後、
>g++ test_json.cpp -o test_json -I c:/Users/Ebata/json/include (git cloneが展開された場所にjson/includeというディレクトリができているので、そこをダイレクトに指示する)
を行い、./test_json を実施したら、
さくっと動きました。
では、次にこのJSONをUDP通信で飛ばしてみます。
この↑のプログラムを前提とします
■C++送信プログラム (キモは、std::string jj = j.dump(); です)
// g++ test_send_json.cpp -o test_send_json -I C:/Users/Ebata/json/include/ -lwsock32 -lws2_32 (Windows版)
#include <stdio.h>
#include <string.h>
#include <nlohmann/json.hpp>
#include <iostream>
#include "simple_udp_win.h" // https://wp.kobore.net/江端さんの技術メモ/post-1959/
//#include "simple_udp.h"
//simple_udp udp0("0.0.0.0",12345); // これはWindowでは動かない
//simple_udp udp0("192.168.0.8",12345); // これは使わない方がいい
simple_udp udp0("127.0.0.1",12345); // ホストOSのUDPの受信側
int main(int argc, char **argv){
using json = nlohmann::json;
json j;
j["pi"] = 3.141;
j["happy"] = true;
j["name"] = "Niels";
j["nothing"] = nullptr;
j["answer"]["everything"] = 42;
j["list"] = { 1, 0, 2 }; // [1,0,2]
j["object"] = { {"currency", "USD"}, {"value", 42.99} }; // {"currentcy": "USD", "value": 42.99}
std::cout << j << std::endl; // cout
std::string jj = j.dump(); // これが重要(これを見つけるのに時間がかかった)
udp0.udp_send(jj);
return 0;
}
■C++受信プログラム (キモは、json j = json::parse(rdata); です)
// g++ test_recv_json.cpp -o test_recv_json -I C:/Users/Ebata/json/include/ -lwsock32 -lws2_32
#include <stdio.h>
#include <string.h>
#include <nlohmann/json.hpp>
#include <iostream>
#include "simple_udp_win.h" // https://wp.kobore.net/江端さんの技術メモ/post-1959/
//#include "simple_udp.h"
//simple_udp udp0("0.0.0.0",12345); // これはWindowsでは動かない
//simple_udp udp0("192.168.0.8",12345); // これは使わない方がいい
simple_udp udp0("127.0.0.1",12345); // これを使うのが無難
int main(int argc, char **argv){
using json = nlohmann::json;
json j;
udp0.udp_bind();
while (1){
std::string rdata=udp0.udp_recv();
j = json::parse(rdata); // これが重要(これを見つけるのに時間がかかった)
// j = json::parse(rdata.c_str()); これでも動くようだが
std::cout << j << std::endl; // cout
}
return 0;
}
さて、そろそろ詰めに入ろうか。
■GOのJSONのUDP受信プログラム(上記の「C++送信プログラム」と対向で動くもの)
// test_recv_json.go
// go run test_recv_json.go
// golangによるjsonのudp受信"だけ"するプログラム
package main
import (
"encoding/json"
"fmt"
"net"
)
type Message struct { // とりあえず3つ
Pi float64 `json:"pi"`
Happy bool `json:"happy"`
Name string `json:"name"`
}
func main() {
addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:12345")
sock, _ := net.ListenUDP("udp", addr)
var j Message
i := 0
for {
i++
buf := make([]byte, 1024)
rlen, _, err := sock.ReadFromUDP(buf)
if err != nil {
fmt.Println(err)
}
str := string(buf[0:rlen])
fmt.Println(str)
// 受信したメッセージをJSON形式に格納する
json.Unmarshal(buf[0:rlen], &j)
// JSONに格納したデータを見る
fmt.Println(j)
fmt.Println(j.Pi)
fmt.Println(j.Happy)
fmt.Println(j.Name)
}
}
■GOのJSONのUDP送信プログラム(上記の「C++受信プログラム」と対向で動くもの)
// test_send_json.go
// go run test_send_json.go
// golangによるjsonのudp送信"だけ"するプログラム
package main
import (
"encoding/json"
"fmt"
"log"
"net"
)
type Message struct { // とりあえず3つ
Pi float64 `json:"pi"`
Happy bool `json:"happy"`
Name string `json:"name"`
}
func main() {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12345")
if err != nil {
log.Fatal(err)
}
conn, _ := net.DialUDP("udp", nil, addr)
if err != nil {
log.Fatal(err)
}
var j Message
j.Pi = 3.1415
j.Happy = false
j.Name = "Ebata"
s, _ := json.Marshal(j)
n, err := conn.Write(s) // WriteToUDPを使ってはならない
fmt.Printf("dial send: bytes=%d to=%s\n", n, addr.String())
}
以上