Top.Deck
Top.Deck

Reputation: 1097

Replace part of the String by Regular Expression

My String input is something like:

{"key1":"value1","key2":"{\"key2_1\":\"123\",\"key2_2\":\"456\",\"key2_3\":\"33333\"}"}

The value fields in the above JSON could contain characters such as ", \ and so on. For your convience here is the formatted version:

{
    "key1": "value1",
    "key2": "{\"key2_1\":\"123\",\"key2_2\":\"456\",\"key2_3\":\"33333\"}"
}

I want to use Gson to convert the String into a Foo Object:

class Foo {
    private String key1;
    private Bar key2;
    ...
}

class Bar {
    private String key2_1;
    private String key2_2;
    private String key2_3;
    ...
}

Here's my regular expression:

String regexp = "\\{[\"a-zA-Z-0-9:,\\\\]*\"key2\":\"\\{\\\\\"key2_1\\\\\":\\\\\"[a-zA-Z0-9]*\\\\\",\\\\\"key2_2\\\\\":\\\\\"[a-zA-Z0-9]*\\\\\",\\\\\"key2_3\\\\\":\\\\\"[a-zA-Z0-9]*\\\\\"\\}\"\\}[\"a-zA-Z-0-9:,\\\\]*";
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(text);
if(matcher.matches()) {
    ... // TODO: Replace all "{, \" and }" but How???
}

How could I use this regular expression to replace all "{, \".and "} into {, ", } without changing the keys and values in JSON?

Finding the sub-string and using String's replace method will be my backup solution.

Again, my ultimate goal is to parse the input String into my Foo object. Is there a better way rather than using regular expression?

Thank you!

Upvotes: 1

Views: 939

Answers (2)

Top.Deck
Top.Deck

Reputation: 1097

After digging further, I find those two links:

Gson custom deseralizer for one variable in an object

Gson custom seralizer for one variable (of many) in an object using TypeAdapter

I achieved what I want by registering my own JsonDeserializer to GsonBuilder:

private static GsonBuilder gsonBuilder = new GsonBuilder().registerTypeAdapter(Bar.class, new JsonDeserializer<Bar>() {

    @Override
    public Bar deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext context) throws JsonParseException {
        Bar result = new Bar();
        String regexp = "\"\\{\\\\\"key2_1\\\\\":\\\\\"(?s).*\\\\\".\\\\\"key2_2\\\\\":\\\\\"(?s).*\\\\\",\\\\\"key2_3\\\\\":\\\\\"(?s).*\\\\\"\\}\"";
        Pattern pattern = Pattern.compile(regexp);
        Matcher matcher = pattern.matcher(json.toString());
        String modifiedJsonStr = json.toString();
        if(matcher.matches()) {
            modifiedJsonStr = json.toString().replace("\"{", "{").replace("}\"", "}").replace("\\\"", "\"");
        }
        result = new Gson().fromJson(modifiedJsonStr, Bar.class);
        return result;
    }
});

Cheers.

Upvotes: 1

Sergey Prokofiev
Sergey Prokofiev

Reputation: 1885

The golden rule is DO NOT USE REGULAR EXPRESSIONS FOR SUCH THINGS :) My advice is too look to the JSON mappers, for example Jackson

All you need to do:

  1. Fix JSON in your example, here is no need double quotes around nested {
  2. Add Jackson dependencies

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    
  3. Create ObjectMapper and let him handle your JSON string

    ObjectMapper mapper = new ObjectMapper();
    Foo foo = mapper.readValue( "{\"key1\":\"value1\",\"key2\":"
         + " {\"key2_1\":\"123\",\"key2_2\":\"456\",\"key2_3\":\"33333\"}}", Foo.class);
    System.out.println(foo.toString());
    

Hope it helps!

Upvotes: 3

Related Questions