I have a file in JSON format. Gson parser crashes when it encounters a blank in it, as in State = "West Virginia", but it can parse "West-Virginia" where the blank character is replaced. I am using BufferedReader in Java.
But if I pass the same string hard-coded, the parser works.
import java.io.* ;
import com.google.gson.*;
public class gson_test {
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
BufferedReader br2 = null ;
String jsonStr = "[{month = august, weather:clear}, [333] , {addr : {place = {city = city_name, county : its_name}, state = \"West Virginia\" } } ]" ;
// System.out.printf("json-str : %s \n", jsonStr);
GsonParseStr(jsonStr, (JsonElement) null );
try {
String file2read_json = "c:\\enter\\filename\\here";
br2 = new BufferedReader(new FileReader(file2read_json));
// https://sites.google.com/site/gson/gson-user-guide#TOC-Array-Examples
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
Object obj2 = gson.fromJson(br2, Object.class); // parses json-str into an object
GsonParseStr(obj2.toString(), (JsonElement) null );
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br2 != null) {
br2.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
static void GsonParseStr(String jsonStr, JsonElement elem) {
JsonParser parser2 = new JsonParser();
elem = parser2.parse(jsonStr); // this stmt crashes for the blank char
System.out.printf("parse str : %s \n", jsonStr);
}
}
My file's content is:
[{month = august, weather:clear}, [333] , {addr : {place = {city = city_name, county : its_name}, state = "West.Virginia" } } ]
If I change "West.Virginia" to "West Virginia" the program crashes.
The file should get parsed the same way as 'file-contents in the form of raw string'.
PS : As suggested by JPinzon, I need quotes around (West Virginia) in the file, which I did have. But they have to be further escaped. Thus : (State: "West Virginia") won't do; it should be (State: "\"West Virginia\""). Optionally, the key 'State' can have double-quotes around it, but that is optional.
Try fixing your JSON to this:
[{"month":"august", "weather":"clear"}, [333], {"addr":{"place":{"city":"city_name", "county":"its_name"}, "state":"West Virginia"}}]
... or nicely formatted:
[
{
"month":"august",
"weather":"clear"
},
[
333
],
{
"addr":{
"place":{
"city":"city_name",
"county":"its_name"
},
"state":"West Virginia"
}
}
]
If you debug, you will see that the string obj2.toString() doesn't contain quotes around "West Virginia" because the gson.fromJson(br2, Object.class) has removed them while parsing. That's why it crashes.
To avoid this error you can try adding escaped quotes in your file like this state = "\"West Virginia\""
Related
The code is:
public JSONArray tree_data() {
JSONArray result = new JSONArray();
JSONArray nodes = new JSONArray();
try {
String query= "select parent_names.name as parent_name, child_names.name as child_name, parent_child.title from parent_child INNER join parent_names on parent_names.id=parent_child.parent_id\r\n" +
" INNER join child_names on child_names.id=parent_child.child_id order by parent_names.name;";
Statement td = this.con.createStatement();
ResultSet rst=td.executeQuery(query);
String parent="";
int i=0;
while(rst.next())
{
JSONObject childs = new JSONObject();
JSONObject obj1 = new JSONObject();
String nowparent=rst.getString("parent_name");
if(parent.equals(nowparent)) {
childs.put("text",rst.getString("child_name"));
childs.put("title", rst.getString("title"));
nodes.put(childs);
}else {
parent=nowparent;
obj1.put("text", parent);
childs.put("text",rst.getString("child_name"));
childs.put("title", rst.getString("title"));
nodes.put(childs);
}obj1.put("nodes", nodes);
result.put(obj1);
}
}
catch (Exception e) {
System.out.print(e);
}
System.out.print(result);
return result;
}
I want this JSON Output
[
{
text: 'Order',
nodes: [
{
text: 'countrywise',
title: 'sss'
},
{
text: 'factorywise',
title: 'ffff'
}
]
},
{
text: 'sales',
nodes: [
{
text: 'countrywise',
title: 'sss'
},
{
text: 'factorywise',
title: 'ffff'
},
{
text: 'Season',
title: 'eeee'
}
]
}
];
This is the database.
parent_name child_name title
Order,
Seoson,
sss, / /
Order, Customer,
ccc, //
Slaes,
Season,
sssss, //
Slaes,
Customer,
ssssds, //
Slaes,
country,
sssdsds
more ways are using but I can't solved it. I think problems have a loop but not showing what is the problem in this loop. please help this solve this question. thank you
correct some codes. now working
JSONObject childs = new JSONObject();
JSONObject obj1 = new JSONObject();
String nowparent=rst.getString("parent_name");
if(parent.equals(nowparent)) {
childs.put("parent",rst.getString("child_name"));
childs.put("title", rst.getString("title"));
nodes.put(childs);
}else {
nodes=new JSONArray();
obj1.put("nodes", nodes);
parent=nowparent;
obj1.put("parent", nowparent);
childs.put("parent",rst.getString("child_name"));
childs.put("title", rst.getString("title"));
nodes.put(childs);
result.put(obj1);
I have this lookup json where it display suggested word. If I input "T" in the editText all values that has "t" in its word will display in the suggested list.
It's already implemented.
what I wanted to do is, if I select a code in spinner, the suggested display value will be based on the selected code.
Here is my json for my spinner
{
"products"{
"BI-BIKE",
"CA-CAR",
"MO-MOTOR",
"TR-TRICYCLE"
}
}
Here is my json for lookupjson
{
"BI": {
"brand": {
"GNT": "GIANT",
"TRL": "TREK",
"CNN": "CDALE",
"STC": "SANTA",
}
},
"CA": {
"brand": {
"AIC": "AICHI",
"BRI": "BRIGDESTONE",
"CON": "CONTINENTAL",
"DUN": "DUNLOP",
}
},
"MO": {
"brand": {
"CAN": "CANON",
"CAS": "CIO",
"FUJ": "FUJ",
"GPR": "PRO",
}
}
}
What I need to do is
If I select "BI" , and I type "T" in the editText field, all values from "BI" code with "t" will display.
first I need to get the first word before the (-) for me to check the code After getting the code check first the code before displaying suggested words.
here is the code where I display the suggested values without the connection from the selected in spinner.
private void loadLookupCategoryJson() {
mLookupProducts = new ArrayList<>();
mArrayStringLookupProduct = new ArrayList<String>();
try {
JSONObject json = new JSONObject(loadLookupBrandJSON());
Iterator<String> keys = json.keys();
while (keys.hasNext()) {
String key = keys.next();
JSONObject obj = (JSONObject) json.get(key);
JSONObject brand = obj.getJSONObject(Keys.CATEGORY_BRAND);
JSONObject desc = obj.getJSONObject(Keys.CATEGORY_DESC);
final String productCode = mProductDescriptionCd.split("-")[0];
if (productCode.equals(brand)){
Iterator<String> brandKeys = brand.keys();
while (brandKeys.hasNext()) {
String bKey = brandKeys.next();
mArrayStringLookupProduct.add((String) brand.get(bKey));
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Expected Result
Selected Products: BI-BIKE
Inputted text from TextField: T
Display suggested word:
GIANT
TREK
SANTA
Actual Result
Selected Products: BI-BIKE
Inputted text from TextField: T
Display suggested word:
GIANT
TREK
SANTA
BRIGDESTONE
CONTINENTAL
i have this fragment of JSON code that i want to parse: basically i want to store the "effective time" and "purpose", that you can see inside the "results" json array using Java(Android Studio), but i'm struggling doing it as it's my first time dealing with JSON.
{
"results": [
{
"effective_time": "20121114",
"inactive_ingredient": [
"Inactive ingredients *acetylated monoglycerides, *anhydrous lactose, *carnauba wax, colloidal silicon dioxide,*corn starch, *croscarmellose sodium, D&C Yellow #10 Aluminum Lake, FD&C Yellow #6 Aluminum Lake, hypromellose, *hypromellose phthalate, *iron oxide Yellow (iron oxide ochre), methacrylic acid copolymer, microcrystalline cellulose, *mineral oil, *polyethylene glycol (PEG)-400, *polysorbate 80, povidone, pregelatinized starch, *propylene glycol, *simethicone, silicon dioxide, sodium bicarbonate, sodium hydroxide, sodium lauryl sulfate, starch, stearic acid, talc, titanium dioxide, triacetin, and triethyl citrate. *May also contain."
],
"purpose": [
"Purpose Pain reliever"
],
"keep_out_of_reach_of_children": [
"Keep out of reach of children In case of overdose, get medical help or contact a Poison Control Center right away."
]
...
...
}
]
}
this is my code so far
String drugDescription="no description";
try{
JSONObject jsonQueryResult = new JSONObject(JSONFILE);
JSONArray jsonResultArray = jsonQueryResult.getJSONArray("result");
JSONObject jsonDrugDescription = jsonResultArray.getJSONObject(0);
drugDescription = jsonDrugDescription.toString();
}
catch(JSONException e){
e.printStackTrace();
}
searchResultTextView.setText(drugDescription);
drugDescription is still showing "no description"
thank you for the help!
If you are new you should go through some tutorial on Json parsing here.
For getting the effective_time and purpose you can do as:
try {
JSONObject jsonObject = new JSONObject(json);
JSONArray firstResult = jsonObject.getJSONArray("results");
if (firstResult != null && firstResult.length() > 0) {
for (int i=0; i<firstResult.length(); i++) {
JSONObject result = firstResult.getJSONObject(i);
// This is your effective_time;
String effective_time = result.getString("effective_time");
JSONArray purpose = result.getJSONArray("purpose");
if (purpose != null && purpose.length() > 0) {
for (int j=0; j<purpose.length(); j++) {
// This is the purpose;
String purposeData = purpose.getString(j);
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
I have JsonNode result that I want to print out. So far, I am using:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
File outputFile = new File(
getCurOutputDir(), String.format("out.json", getClass().getSimpleName())
);
mapper.writeValue(new FileOutputStream(outputFile), resultNode);
which outputs something like:
{
"A" : [ {
"Ai" : {
"Ai1" : 42,
"Ai2" : 55
}
} ],
"B" : [ 86 ]
}
but I need it to be in this specific format:
{
"A" : [
{
"Ai" : {
"Ai1" : 42,
"Ai2" : 55
}
}
],
"B" : [
86
]
}
For context, I am transitioning from JSONObject to Jackson, so the second output is the one that is outputted by JSONObject.serialize().
Also, is there a name for each of the format presented above? It seems like it abides by different standards.
You can customize how Jackson will indent the output. There are different ways to achieve it, according to the Jackson version you are using.
Jackson 2.5 and newer versions
Do the following:
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new DefaultIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter); // Indent JSON arrays
ObjectMapper mapper = new ObjectMapper();
mapper.writer(printer).writeValue(new FileOutputStream(outputFile), node);
By default, 2 spaces will be used. For a different number of spaces, use the DefaultIndenter constructor that receives a string to indent levels and the line separator:
Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF);
Jackson 2.4 and older versions
Do the following:
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new Lf2SpacesIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter); // Indent JSON arrays
ObjectMapper mapper = new ObjectMapper();
mapper.writer(printer).writeValue(new FileOutputStream(outputFile), node);
The Lf2SpacesIndenter is limited to 2 spaces and you cannot change it.
If you need a different number of spaces, you need to write your custom implementation. Here's one that uses the same code as the DefaultIndenter introduced in Jackson 2.5:
/**
* Default linefeed-based indenter.
*/
public class CustomSpaceIndenter extends DefaultPrettyPrinter.NopIndenter {
public final static String SYS_LF;
static {
String lf;
try {
lf = System.getProperty("line.separator");
} catch (Throwable t) {
lf = "\n"; // fallback when security manager denies access
}
SYS_LF = lf;
}
public static final CustomSpaceIndenter SYSTEM_LINEFEED_INSTANCE =
new CustomSpaceIndenter(" ", SYS_LF);
/**
* We expect to rarely get indentation deeper than this number of levels,
* and try not to pre-generate more indentations than needed.
*/
private final static int INDENT_LEVELS = 16;
private final char[] indents;
private final int charsPerLevel;
private final String eol;
/**
* Indent with two spaces and the system's default line feed
*/
public CustomSpaceIndenter() {
this(" ", SYS_LF);
}
/**
* Create an indenter which uses the <code>indent</code> string to indent one level
* and the <code>eol</code> string to separate lines.
*/
public CustomSpaceIndenter(String indent, String eol) {
charsPerLevel = indent.length();
indents = new char[indent.length() * INDENT_LEVELS];
int offset = 0;
for (int i=0; i<INDENT_LEVELS; i++) {
indent.getChars(0, indent.length(), indents, offset);
offset += indent.length();
}
this.eol = eol;
}
public CustomSpaceIndenter withLinefeed(String lf) {
if (lf.equals(eol)) {
return this;
}
return new CustomSpaceIndenter(getIndent(), lf);
}
public CustomSpaceIndenter withIndent(String indent) {
if (indent.equals(getIndent())) {
return this;
}
return new CustomSpaceIndenter(indent, eol);
}
public String getEol() {
return eol;
}
public String getIndent() {
return new String(indents, 0, charsPerLevel);
}
#Override
public boolean isInline() {
return false;
}
#Override
public void writeIndentation(JsonGenerator jg, int level) throws IOException {
jg.writeRaw(eol);
if (level > 0) { // should we err on negative values (as there's some flaw?)
level *= charsPerLevel;
while (level > indents.length) { // unlike to happen but just in case
jg.writeRaw(indents, 0, indents.length);
level -= indents.length;
}
jg.writeRaw(indents, 0, level);
}
}
}
It can be used as following:
Indenter indenter = new CustomSpaceIndenter(" ", CustomSpaceIndenter.SYS_LF);
You can setup a custom DefaultPrettyPrinter using this:
DefaultPrettyPrinter pp = new DefaultPrettyPrinter();
pp.indentObjectsWith(new Lf2SpacesIndenter());
pp.indentArraysWith(new Lf2SpacesIndenter("\r\n"));
mapper.writer(pp).writeValue(new FileOutputStream(outputFile), resultNode);
Take a look at the method provided by DefaultPrettyPrinter HERE
I'm trying to use and understand AntLR, this is new to me. My purpose is to read a source code file written in C and extract from it the identifiers (variables and function names).
In my C grammar (file C.g4) consider:
identifierList
: Identifier
| identifierList Comma Identifier
;
Identifier
: IdentifierNondigit
( IdentifierNondigit
| Digit
)*
;
After generation of parser and listener I create my own listener to the identifierList.
Note that MyCListener class extends CBaseListener:
public class MyCListener extends CBaseListener {
#Override
public void enterIdentifierList(CParser.IdentifierListContext ctx) {
List<ParseTree> children = ctx.children;
for (ParseTree parseTree : children) {
System.out.println(parseTree.getText());
}
}
Then I have this in main class:
String fileurl = "C:/example.c";
CLexer lexer;
try {
lexer = new CLexer(new ANTLRFileStream(fileurl));
CommonTokenStream tokens = new CommonTokenStream(lexer);
CParser parser = new CParser(tokens);
CParser.IdentifierListContext identifierContext = parser.identifierList();
ParseTreeWalker walker = new ParseTreeWalker();
MyCListener listener = new MyCListener();
walker.walk(listener, identifierContext);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
Where example.c is:
int main() {
// this is C
int i=0; // i is int
/* double j=0.0;
C
*/
}
What am I doing wrong?
Maybe I didn't write MyCListener properly, or identifierList is not what I need to listen... Really don't know. I'm sorry, but I didn't even understand my output, why is there a lexical error?:
line 3:4 mismatched input '(' expecting {<EOF>, ','}
main
(
)
{
int
i
=
0
;
}
As you see, I'm very confused about this. Can somebody help me ? Please...
With this line:
CParser.IdentifierListContext identifierContext = parser.identifierList();
you're trying to parse your entire input as an identifierList. But your input isn't just that.
Assuming you're using the C.g4 from the ANTLR4 Github repository, try to let the parser start at the entry point of the grammar (which is the rule compilationUnit):
MyCListener listener = new MyCListener();
ParseTreeWalker.DEFAULT.walk(listener, parser.compilationUnit());
EDIT
Here's a quick demo:
public class Main {
public static void main(String[] args) throws Exception {
final List<String> identifiers = new ArrayList<String>();
String source = "int main() {\n" +
"\n" +
"// this is C\n" +
"\n" +
" int i=0; // i is int\n" +
" /* double j=0.0;\n" +
" C\n" +
" */\n" +
"}";
CLexer lexer = new CLexer(new ANTLRInputStream(source));
CParser parser = new CParser(new CommonTokenStream(lexer));
ParseTreeWalker.DEFAULT.walk(new CBaseListener(){
#Override
public void enterDirectDeclarator(#NotNull CParser.DirectDeclaratorContext ctx) {
if (ctx.Identifier() != null) {
identifiers.add(ctx.Identifier().getText());
}
}
// Perhaps override other rules that use `Identifier`
}, parser.compilationUnit());
System.out.println("identifiers -> " + identifiers);
}
}
which would print:
identifiers -> [main, i]