Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions haskell/main/SBP2PRETTYJSON.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# OPTIONS_GHC -fno-cse #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module: SBP2PRETTYJSON
-- Copyright: Copyright (C) 2019 Swift Navigation, Inc.
-- License: LGPL-3
-- Maintainer: Pasi Miettinen <dev@swiftnav.com>
-- Stability: experimental
-- Portability: portable
--
-- SBP to JSON tool - reads SBP binary from stdin and sends SBP JSON
-- to stdout.

import BasicPrelude hiding (map, print)
import Control.Monad.Trans.Resource
import Data.Aeson.Encode.Pretty
import Data.ByteString.Lazy hiding (ByteString, map)
import Data.Conduit
import Data.Conduit.Binary
import Data.Conduit.List
import Data.Conduit.Serialization.Binary
import SwiftNav.SBP
import System.Console.CmdArgs
import System.IO

data Cfg = Cfg {skiporder :: Bool
,spaces :: Int}
deriving (Show, Data, Typeable)

defaultCfg :: Cfg
defaultCfg = Cfg{skiporder = False
,spaces = 0}

-- | Encode a SBPMsg to a line of JSON.
encodeLine :: Cfg -> SBPMsg -> ByteString
encodeLine c v = toStrict
$ encodePretty'
(defConfig {confIndent = Spaces (spaces c),
confCompare = if (skiporder c) then mempty else compare}) v <> "\n"

main :: IO ()
main = do
cfg <- cmdArgs defaultCfg
runResourceT $
sourceHandle stdin
=$= conduitDecode
=$= map (encodeLine cfg)
$$ sinkHandle stdout
16 changes: 16 additions & 0 deletions haskell/sbp.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ executable sbp2json
, sbp
default-language: Haskell2010

executable sbp2prettyjson
hs-source-dirs: main
main-is: SBP2PRETTYJSON.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
build-depends: aeson-pretty
, base
, basic-prelude
, binary-conduit
, bytestring
, cmdargs
, conduit
, conduit-extra
, resourcet
, sbp
default-language: Haskell2010

executable json2sbp
hs-source-dirs: main
main-is: JSON2SBP.hs
Expand Down
53 changes: 29 additions & 24 deletions python/sbp/client/loggers/json_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
import warnings


class JSONLogger(BaseLogger):
class JSONLoggerBase(BaseLogger):
"""
JSONLogger
JSONLoggerBase

The :class:`JSONLogger` logs JSON records.
The :class:`JSONLoggerBase` base class for JSON loggers.
"""

def __init__(self, handle, tags={}, dispatcher=None, sort_keys=False):
BaseLogger.__init__(self, handle, tags, dispatcher)
self._sort_keys=sort_keys

def fmt_msg(self, data, **metadata):
if metadata:
metadata.update(self.tags)
Expand All @@ -31,10 +35,26 @@ def fmt_msg(self, data, **metadata):

return data

def __call__(self, msg, **metadata):
output = self.dump(msg, **metadata)
if output:
self.handle.write(output + "\n")


class JSONLogger(JSONLoggerBase):
"""
JSONLogger

The :class:`JSONLogger` logs JSON records.
"""

def dump(self, msg, **metadata):
try:
data = self.dispatch(msg).to_json_dict()
return json.dumps(self.fmt_msg(data, **metadata), allow_nan=False)
return json.dumps(self.fmt_msg(data, **metadata),
allow_nan=False,
sort_keys=self._sort_keys,
separators=(',',':'))
except (ValueError, UnicodeDecodeError):
try:
warn = "Bad values in JSON encoding for msg_type %d for msg %s" \
Expand All @@ -44,27 +64,14 @@ def dump(self, msg, **metadata):
except (ValueError, UnicodeDecodeError):
return None

def __call__(self, msg, **metadata):
output = self.dump(msg, **metadata)
if output:
self.handle.write(output + "\n")


class JSONBinLogger(BaseLogger):
class JSONBinLogger(JSONLoggerBase):
"""
JSONBinLogger

The :class:`JSONLogger` logs JSON records without expanding the fields.
"""

def fmt_msg(self, data, **metadata):
if metadata:
metadata.update(self.tags)
metadata['data'] = data
return metadata

return data

def dump(self, msg, **metadata):
try:
data = {
Expand All @@ -75,7 +82,10 @@ def dump(self, msg, **metadata):
'payload': base64.standard_b64encode(msg.payload).decode('ascii'),
'crc': msg.crc
}
return json.dumps(self.fmt_msg(data, **metadata), allow_nan=False)
return json.dumps(self.fmt_msg(data, **metadata),
allow_nan=False,
sort_keys=self._sort_keys,
separators=(',',':'))
except (ValueError, UnicodeDecodeError):
try:
warn = "Bad values in JSON encoding for msg_type %d for msg %s" \
Expand All @@ -85,11 +95,6 @@ def dump(self, msg, **metadata):
except (ValueError, UnicodeDecodeError):
return None

def __call__(self, msg, **metadata):
output = self.dump(msg, **metadata)
if output:
self.handle.write(output + "\n")


class JSONLogIterator(LogIterator):
"""
Expand Down
4 changes: 2 additions & 2 deletions python/sbp/msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ def to_binary(self):
ret += struct.pack("<H", crc)
return ret

def to_json(self):
def to_json(self, sort_keys=False):
"""Produce a JSON-encoded SBP message.

"""
d = self.to_json_dict()
return json.dumps(d)
return json.dumps(d, sort_keys=sort_keys)

@staticmethod
def from_json(s):
Expand Down