NATS Logo by Example

JSON for Message Payloads in Messaging

The basic structure of a NATS message modeled in the client libraries includes the subject the message was published to, the application-defined payload, and an optional set of headers (for requests, there is also a reply-to subject). The payload is a sequence of bytes, so it is up to the application to define how to serialize and deserialize the payload.

JSON is ubiquitous and simple data-interchange format that is supported in virtually all programming languages. This example demonstrates how to serialize and deserialize a message payload using a JSON library.

CLI Go Python JavaScript Rust C# Java Ruby Elixir Crystal C
Jump to the output or the recording
$ nbe run messaging/json/crystal
View the source code or learn how to run this example yourself

Code

require "nats"
require "json"

Use the JSON::Serializable mixin to be able to serialize and deserialize a struct we define.

struct Payload
  include JSON::Serializable


  getter foo : String
  getter bar : UInt8


  def initialize(@foo, @bar)
  end
end

Get the NATS_URL from the environment or fallback to the default. This can be a comma-separated string. We convert it to an Array(URI) to pass to the NATS client.

servers = ENV.fetch("NATS_URL", "nats://localhost:4222")
  .split(',')
  .map { |url| URI.parse(url) }

Create a client connection to an available NATS server.

nats = NATS::Client.new(servers)

When the program exits, we close the NATS client which waits for any pending messages (published or in a subscription) to be flushed.

at_exit { nats.close }

Create a subscription. We will receive both valid and invalid JSON here, so we rescue the JSON::ParseException.

nats.subscribe "foo" do |msg|
  json = String.new(msg.body)
  payload = Payload.from_json(json)


  puts "received valid JSON: #{payload}"
rescue JSON::ParseException
  puts "received invalid JSON: #{json}"
end

Construct and serialize a Payload struct.

payload = Payload.new(foo: "bar", bar: 27).to_json

Publish the serialized payload

nats.publish "foo", payload
nats.publish "foo", "not json"

Output

received valid JSON: Payload(@foo="bar", @bar=27)
received invalid JSON: not json

Recording

Note, playback is half speed to make it a bit easier to follow.