2

I am getting a string response from server like this..

[
 Anchor{anchorName='&loreal_lip_balm',
    clientName='loreal india',

  anchorPrice=10,
        campaigns=[
                Campaign{
                        campaignId='loreal_camp1',

                        question='How to Turn Your Melted Lipstick into a Tinted Lip Balm',

                        startDate=2015-08-04,
                        endDate=2015-08-04,
                        imageURL='null',

                        regionCountry='ALL',
                        rewardInfo='null',
                        campaignPrice=20,

                        options=null
              }
      ]},
    Anchor{

            anchorName='&loreal_total_repair_5',
            clientName='loreal india',
            anchorPrice=125,

          campaigns=[
                    Campaign{
                    campaignId='loreal_camp2',
                            question='Is it a good
                         product to buy?',
                            startDate=2015-08-04,
                            endDate=2015-08-04,

                         imageURL='null',
                            regionCountry='ALL',
                            rewardInfo='null',

                         campaignPrice=20,
                            options=null
                    }
                ]
       }
 ].

can anybody tell me how to parse this.It is not a json response.

6
  • The easiest way would be Scala's magic parser-combinator framework. Scala runs of the JVM so you can then use your parsing library directly from Java. The alternative would be to use a library likejparsec. I would not recommend parsing this yourself by hand. Commented Aug 5, 2015 at 10:21
  • What is your expected parsed result? Commented Aug 5, 2015 at 11:22
  • i need to get anchroname ,clientname,anchorprice ,campaigns values Commented Aug 5, 2015 at 11:46
  • 1
    proper response format Commented Aug 7, 2015 at 10:45
  • 1
    The response seems to have arrays and maps. If you are comfortable in Java a simple recursive descent parser seems to be a good bet. Commented Aug 7, 2015 at 11:02

3 Answers 3

2

I used hand coded parsers for simple languages where I felt that using http://www.antlr.org/ or https://javacc.java.net to be a bit heavy. I used the same structure for parsing JSON, CSS a simple template. Modified it to parse your response. See whether it helps.

package snippet;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import snippet.RecursiveDescentParser.Token.TokenType;

public class RecursiveDescentParser {

    // @formatter:off
    final static String text = "" +
            "[" + 
            " Anchor{anchorName='&loreal_lip_balm'," + 
            "    clientName='loreal india'," + 
            "" + 
            "  anchorPrice=10," + 
            "        campaigns=[" + 
            "                Campaign{" + 
            "                        campaignId='loreal_camp1'," + 
            "" + 
            "                        question='How to Turn Your Melted Lipstick into a Tinted Lip Balm'," + 
            "" + 
            "                        startDate=2015-08-04," + 
            "                        endDate=2015-08-04," + 
            "                        imageURL='null'," + 
            "" + 
            "                        regionCountry='ALL'," + 
            "                        rewardInfo='null'," + 
            "                        campaignPrice=20," + 
            "" + 
            "                        options=null" + 
            "              }" + 
            "      ]}," + 
            "    Anchor{" + 
            "" + 
            "            anchorName='&loreal_total_repair_5'," + 
            "            clientName='loreal india'," + 
            "            anchorPrice=125," + 
            "" + 
            "          campaigns=[" + 
            "                    Campaign{" + 
            "                    campaignId='loreal_camp2'," + 
            "                            question='Is it a good" + 
            "                         product to buy?'," + 
            "                            startDate=2015-08-04," + 
            "                            endDate=2015-08-04," + 
            "" + 
            "                         imageURL='null'," + 
            "                            regionCountry='ALL'," + 
            "                            rewardInfo='null'," + 
            "" + 
            "                         campaignPrice=20," + 
            "                            options=null" + 
            "                    }" + 
            "                ]" + 
            "       }" + 
            " ]" + 
            "";
    // @formatter:on

    static class Token {
        enum TokenType {
            OPEN_BRACKET, CLOSE_BRACKET, OPEN_BRACE, CLOSE_BRACE, STRING, NAME, COMMA, EQUALS, INTEGER, DATE, EOF, NULL;
        }

        private String text;
        private TokenType type;

        public Token(TokenType type) {
            this(type, null);
        }

        public Token(TokenType type, String text) {
            this.type = type;
            this.text = text;
        }

        public TokenType getType() {
            return type;
        }

        public String getText() {
            return text;
        }

        @Override public String toString() {
            return "Token [text=" + text + ", type=" + type + "]";
        }

    }

    static class TokenReader {
        private PushbackReader reader;

        public TokenReader(Reader reader) {
            this.reader = new PushbackReader(reader);
        }

        public Token nextToken() throws IOException {
            Token t = nextTokenx();
            System.out.println("Got: " + t);
            return t;
        }

        public Token nextTokenx() throws IOException {
            int c;
            while ((c = reader.read()) != -1 && Character.isWhitespace((char) c))
                ;
            if (c == -1)
                return new Token(TokenType.EOF);
            switch (c) {
            case '[':
                return new Token(TokenType.OPEN_BRACKET);
            case ']':
                return new Token(TokenType.CLOSE_BRACKET);
            case '{':
                return new Token(TokenType.OPEN_BRACE);
            case '}':
                return new Token(TokenType.CLOSE_BRACE);
            case ',':
                return new Token(TokenType.COMMA);
            case '=':
                return new Token(TokenType.EQUALS);
            default:
                if (Character.isDigit(c))
                    return readIntegerOrDate(c);
                if (c == '\'')
                    return readString(c);
                if (Character.isJavaIdentifierStart(c))
                    return readName(c);
                throw new RuntimeException("Invalid character '" + ((char) c) + "' in input");
            }
        }

        private Token readName(int c) throws IOException {
            StringBuilder sb = new StringBuilder();
            sb.append((char) c);
            while ((c = reader.read()) != -1 && Character.isJavaIdentifierPart(c))
                sb.append((char) c);
            if (c != -1)
                reader.unread(c);
            if ("null".equals(sb.toString()))
                return new Token(TokenType.NULL);
            return new Token(TokenType.NAME, sb.toString());
        }

        private Token readString(int end) throws IOException {
            StringBuilder sb = new StringBuilder();
            int c;
            while ((c = reader.read()) != -1 && c != end)
                sb.append((char) c);
            return new Token(TokenType.STRING, sb.toString());
        }

        private Token readIntegerOrDate(int c) throws IOException {
            StringBuilder sb = new StringBuilder();
            sb.append((char) c);
            while ((c = reader.read()) != -1 && Character.isDigit((char) c))
                sb.append((char) c);
            if (c == '-') {
                sb.append((char) c);
                return readDate(sb);
            }
            if (c != -1)
                reader.unread(c);
            return new Token(TokenType.INTEGER, sb.toString());
        }

        private Token readDate(StringBuilder sb) throws IOException {
            int c;
            while ((c = reader.read()) != -1 && Character.isDigit((char) c))
                sb.append((char) c);
            if (c == -1)
                throw new RuntimeException("EOF while reading date");
            if (c != '-')
                throw new RuntimeException("Invalid character '" + (char) c + "' while reading date");
            sb.append((char) c);
            while ((c = reader.read()) != -1 && Character.isDigit((char) c))
                sb.append((char) c);
            if (c != -1)
                reader.unread(c);
            return new Token(TokenType.DATE, sb.toString());
        }
    }

    static class Lexer {

        private TokenReader reader;
        private Token current;

        public Lexer(Reader reader) {
            this.reader = new TokenReader(reader);
        }

        public Token expect(TokenType... tt) throws IOException {
            if (current == null)
                current = reader.nextToken();
            for (TokenType tokenType : tt) {
                if (current.getType() == tokenType) {
                    Token r = current;
                    current = null;
                    return r;
                }
            }
            throw new RuntimeException("Expecting one of " + Arrays.asList(tt) + " but got " + current);
        }

        public Token expect1or0(TokenType... tt) throws IOException {
            if (current == null)
                current = reader.nextToken();
            for (TokenType tokenType : tt) {
                if (current.getType() == tokenType) {
                    Token r = current;
                    current = null;
                    return r;
                }
            }
            return null;
        }
    }

    public Object parse(String text) throws IOException {
        return parse(new StringReader(text));
    }

    private Object parse(Reader reader) throws IOException {
        Lexer lexer = new Lexer(reader);
        return parse(lexer);
    }

    private Object parse(Lexer lexer) throws IOException {
        Token t = lexer.expect1or0(TokenType.OPEN_BRACE, TokenType.OPEN_BRACKET, TokenType.EOF);
        if (t == null || t.getType() == TokenType.EOF)
            return null;
        else if (t.getType() == TokenType.OPEN_BRACKET) {
            return parseList(lexer);
        } else {
            return parseMap(null, lexer);
        }
    }

    private List<Object> parseList(Lexer lexer) throws IOException {
        ArrayList<Object> result = new ArrayList<Object>();
        Token tName = lexer.expect1or0(TokenType.NAME);
        while (tName != null) {
            lexer.expect(TokenType.OPEN_BRACE);
            result.add(parseMap(tName.getText(), lexer));
            if (lexer.expect1or0(TokenType.COMMA) != null)
                tName = lexer.expect(TokenType.NAME);
            else
                tName = null;
        }
        lexer.expect(TokenType.CLOSE_BRACKET);
        return result;
    }

    private Object parseMap(String oname, Lexer lexer) throws IOException {
        Map<String, Object> result = new HashMap<String, Object>();
        if (oname != null)
            result.put("objectName", oname);
        Token tName = lexer.expect1or0(TokenType.NAME);
        while (tName != null) {
            String name = tName.getText();
            lexer.expect(TokenType.EQUALS);
            Token next = lexer.expect(TokenType.STRING, TokenType.DATE, TokenType.INTEGER, TokenType.OPEN_BRACKET,
                    TokenType.OPEN_BRACE, TokenType.NULL);
            TokenType tt = next.getType();
            if (tt == TokenType.STRING) {
                result.put(name, next.getText());
            } else if (tt == TokenType.DATE) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    result.put(name, sdf.parse(next.getText()));
                } catch (ParseException e) {
                    return new RuntimeException(e);
                }
            } else if (tt == TokenType.INTEGER) {
                result.put(name, Integer.valueOf(next.getText()));
            } else if (tt == TokenType.OPEN_BRACKET) {
                result.put(name, parseList(lexer));
            } else if (tt == TokenType.OPEN_BRACE) {
                result.put(name, parseMap(null, lexer));
            } else {
                result.put(name, null);
            }
            if (lexer.expect1or0(TokenType.COMMA) != null)
                tName = lexer.expect(TokenType.NAME);
            else
                tName = null;
        }
        lexer.expect(TokenType.CLOSE_BRACE);
        return result;
    }

    public static void main(String[] args) throws IOException {
        RecursiveDescentParser parser = new RecursiveDescentParser();
        Object o = parser.parse(text);
        System.out.println(o);
    }

}
Sign up to request clarification or add additional context in comments.

Comments

2

Here is my suggestion.

I assume as you said that your input from the server is String.

I have build a little method that return the value of the required key.

public String valueFinder(String data, String key){

    int keyValueStart = data.indexOf(key) + key.length() + 1;
    String keyValueRaw = data.substring(keyValueStart, data.length());
    int keyValueEnd = keyValueRaw.indexOf(",");
    String keyValue = keyValueRaw.substring(0, keyValueEnd);
    String value = keyValue.replaceAll("^\'|\'$", "");

    return value;
}

So if you pass the String data generated by the server to the method and the ask for the required key for example for "clientName" it will return loreal india, if you pass/look-for "anchorName" it will return &loreal_lip_balm.

Now you have the concept, you are welcome to change/modify/customize it as you wish to fetch more detailed information in your campaigns or other scenarios.

It is possible to further develop the method to return single key value, a set of keys and values, convert keys and values to JSON or Array, and just name it.

All this can be done on the same concept.

Comments

1

There is a tool called ANTLR which is useful to read data like this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.