Albert Lee Albert Lee - 1 month ago 13
Python Question

AWS API Gateway's querystring is not json format

In aws api gateway, I wanna pass the entire query string into the kinesis through api gateway,

#set($querystring = $input.params().querystring)
"Data": "$util.base64Encode($querystring)"


but the data fetching from kinesis record looks like '{tracker_name=xxxx, tracker=yyyy}', which is not json string format, So I need to take special care of this weird string to make it to json string in aws lambda (Python engine). Any good idea?

Answer

I'm not familiar with the AWS API Gateway, but focusing on the string formatting issue, it is not that hard to write a simple parser to convert it to any other format you want.

As for your description, I write a simple Python parser, hope it can give you some ideas.

class MyParser:

def __init__(self, source):
    # the source string
    self.source = source
    # current position
    self.at = 0
    # current character
    self.ch = source[0] if len(source) > 0 else ''

def error(self, msg):
    '''Print an error message and raise an exception'''

    print '-- Parser abort due to a fatal error: \n-- %s' % msg
    raise ValueError()

def check_char(self, expected):
    '''
    Check if current character is same as the given character.
    If not, raise an exception.
    '''

    if self.at >= len(self.source):
        self.error('At position %d: %c expected, but reached string end' % (self.at, expected))
    elif self.ch != expected:
        self.error('At position %d: %c expected, but %c given' % (self.at, expected, self.ch))

def next_char(self):
    '''Move on to next character in source string.'''

    self.at += 1
    self.ch = self.source[self.at] if len(self.source) > self.at else ''
    return self.ch

def eat_spaces(self):
    '''Eat up white spaces.'''

    while self.ch == ' ':
        self.next_char()

def parse_string(self):
    '''Parse a string value.'''

    s = ''
    while self.ch != '=' and self.ch != ',' and self.ch != '}' and self.at < len(self.source):
        s += self.ch
        self.next_char()
    return s.strip()

def parse_object(self):
    '''Parse an object value.'''

    obj = {}

    # eat '{'
    self.next_char()
    self.eat_spaces()

    while self.ch != '}':
        if self.at >= len(self.source):
            self.error('Malformed source string')

        key = self.parse_string()
        # eat '='
        self.check_char('=')
        self.next_char()
        val = self.parse_value()
        obj[key] = val
        # eat ','
        if self.ch == ',':
            self.next_char()
        self.eat_spaces()

    # eat '}'
    self.next_char()

    return obj

def parse_value(self):
    '''Parse a value.'''

    self.eat_spaces()
    if self.ch == '{':
        return self.parse_object()
    else:
        return self.parse_string()

def parse(self):
    '''Let the game begin.'''

    self.eat_spaces()
    if self.ch != '{':
        self.error('Source string must begin with \'{\'')
    else:
        return self.parse_value()

To use it:

MyParser('{tracker_name=xxxx, tracker=yyyy}').parse()
Comments