转载请注明出处:http://blog.csdn.net/stevenhu_223/article/details/42520233
本博文相关的Demo下载链接:http://download.csdn.net/detail/stevenhu_223/8340451
前言:在开发Android第三方App应用的过程中,特别是涉及到网络请求的App,都会涉及到解析后台返回的数据。而后台返回的数据无非就是两种格式,xml和json格式。如何更好的方便有效的解析这些后台返回的数据,对我们开发者来说是很重要的。接下来将介绍以下几种笔者比较常用的数据解析方式。
一。simple-xml第三方jar包解析xml格式数据
simple-xml是一个xml和对象互转操作工具包,官方网址为:http://simple.sourceforge.net/,jar包可以到官网上下载,笔者使用的是目前最新版本的jar包,名为simple-xml-2.7.1.jar;废话不多说了,代码才是最真实靠谱的力证。
下面是整个Demo工程文件截图,如下图:
该Demo主要是通过simple-xml解析assets目录中的data.xml文件内容数据,然后显示出来;
1.data.xml文件内容如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <?xml version="1.0" encoding="utf-8"?> <dataContent> <group> <groupID>1</groupID> <groupName>第一组</groupName> <member> <name>张三</name> <age>22</age> </member> <member> <name>李四</name> <age>24</age> </member> <member> <name>欧阳雪</name> <age>18</age> </member> </group> <group> <groupID>2</groupID> <groupName>第二组</groupName> <member> <name>司徒静</name> <age>19</age> </member> <member> <name>叶笙</name> <age>26</age> </member> <member> <name>杨风</name> <age>25</age> </member> </group> <group> <groupID>3</groupID> <groupName>第三组</groupName> <member> <name>王龙</name> <age>32</age> </member> <member> <name>西门胜男</name> <age>21</age> </member> <member> <name>张铬</name> <age>45</age> </member> </group> </dataContent> </resources>通过上面的文件内容,我们知道,这个文件内容主要有三组数据,每组数据有个三个成员组,每个成员组都有名字和年龄这两个子元素。Demo中将这些解析出来内容通过ExpandableListView显示出来。
2.主页面MainActivity代码如下:
package com.steven.android.simple.xml.activity; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.simpleframework.xml.core.Persister; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.widget.ExpandableListView; import com.steven.android.simple.xml.adapter.ExpandAdapter; import com.steven.android.simple.xml.parse.DataParseResponse; /** * 描述:主页面 * @author stevenhu223 * */ public class MainActivity extends Activity { private final String TAG = "MainActivity"; private ExpandableListView mExpandableListView; private ExpandAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mExpandableListView = (ExpandableListView) findViewById(R.id.expanlist_content); try { matchAndParseData(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /** * 匹配获取和解析xml文件内容 * @throws Exception */ private void matchAndParseData() throws Exception { InputStream inputStream = getResources().getAssets().open("data.xml"); String dataContent = convertStreamToString(inputStream); String content = ""; //正则表达式匹配 Pattern DATA_PATTERN= Pattern.compile("[\\S\\s]*(<dataContent>[\\s\\S]*</dataContent>)[\\s\\S]*"); Matcher matcher = DATA_PATTERN.matcher(dataContent); if (matcher.matches()) { //获取包含dataContent元素的内容 content = matcher.group(1); } if (!TextUtils.isEmpty(content)) { DataParseResponse dataResponse = parseToBean(DataParseResponse.class, content); mAdapter = new ExpandAdapter(this, dataResponse.mGroupEntities); mExpandableListView.setAdapter(mAdapter); } } /** * 将xml文件内容解析成实体类 * @param type * @param data * @return */ private <T> T parseToBean(Class<T> type , String data) { try { return new Persister().read(type, data, false); } catch (Exception e) { Log.e(TAG, "parse Data error", e); throw new RuntimeException(e); } } /** * 输入流转字符串 * @param is * @return */ public String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }上面的代码中,parseToBean方法的功能就是将xml格式数据解析成对应的实体类,Persister类是simple-xml包中的类。通过调用parseToBean函数将xml内容数据解析封装成DataParseResponse对象,接下来我们看看DataParseResponse的代码。
3.DataParseResponse.java文件代码如下:
package com.steven.android.simple.xml.parse; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; import com.steven.android.simple.xml.entity.GroupEntity; import java.util.List; /** * 描述:解析数据响应类 * 此处的dataContent要对应xml文件中的dataContent元素 * @author stenvenhu223 * */ @Root(name = "dataContent") public class DataParseResponse { @ElementList(inline=true,required=false) public List<GroupEntity> mGroupEntities; }通过上面的代码我们知道,simple-xml包解析xml格式数据成实体类时,实体类中对应需要解析的xml格式数据元素名的注解是非常重要的。这些注释都是来自simple-xml包的。DataParseResponse类中的@Root(name = "NewDataSet")注解表示的是从xml数据根元素dataContent。由于group元素在根元素dataContent中是以数组的形式存在的,所以这里的集合mGroupEntities就表示解析的group元素数组内容集合,必然的它的注解也应为@ElementList(inline=true,required=false)。接下来,我们看看GroupEntity实体类的代码。
4.GroupEntity.java文件代码如下:
package com.steven.android.simple.xml.entity; import java.util.List; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; @Root(name="group") public class GroupEntity { @Element(name="groupID") public String groupId; @Element(name="groupName") public String groupName; @ElementList(inline=true,required=false) public List<MemberEntity> memberEntities; }代码中,@Root(name="group")对应的是xml文件中的group元素。@Element(name="groupID")注解对应的是group元素的子元素groupID,@Element(name="groupName")注解对应的是group元素的子元素groupName。而member元素在group元素中是以数组形式存在的,所以它在GroupEntity中必然也以集合的形式存在,注解也应该为@ElementList(inline=true,required=false);接着,我们解析看看实体类MemberEntity的代码。
5.MemberEntity.java文件代码如下:
@Root(name="member") public class MemberEntity { @Element(required=false) public String name; @Element(required=false) public String age; }MemberEntity代码中的代码注释这里就不多说了,原理和其他的实体类是一致的。
既然要把解析出来的数据通过ExpandableListView显示出来,那么我们就需要创建ExpandableListView对应的适配器,然后填充解析后的实体类形式数据。我们来看看适配器ExpandAdapter的代码。
6.ExpandAdapter.java文件代码如下:
package com.steven.android.simple.xml.adapter; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; import com.steven.android.simple.xml.activity.R; import com.steven.android.simple.xml.custom.ViewHolder; import com.steven.android.simple.xml.entity.GroupEntity; import com.steven.android.simple.xml.entity.MemberEntity; public class ExpandAdapter extends BaseExpandableListAdapter{ private List<GroupEntity> mGroupEntities; private LayoutInflater mInflater; public ExpandAdapter(Context context, List<GroupEntity> list) { mGroupEntities = list; mInflater = LayoutInflater.from(context); } @Override public Object getChild(int groupPosition, int childPosition) { // TODO Auto-generated method stub return mGroupEntities.get(groupPosition).memberEntities.get(childPosition); } @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub return childPosition; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_member_content, parent, false); } TextView text_member_content = ViewHolder.get(convertView, R.id.text_member_content); MemberEntity entity = (MemberEntity)getChild(groupPosition, childPosition); text_member_content.setText(entity.name); return convertView; } @Override public int getChildrenCount(int groupPosition) { // TODO Auto-generated method stub return mGroupEntities.get(groupPosition).memberEntities.size(); } @Override public Object getGroup(int groupPosition) { // TODO Auto-generated method stub return mGroupEntities.get(groupPosition); } @Override public int getGroupCount() { // TODO Auto-generated method stub return mGroupEntities.size(); } @Override public long getGroupId(int groupPosition) { // TODO Auto-generated method stub return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_group_content, parent, false); } TextView text_group_cotent = ViewHolder.get(convertView, R.id.text_group_content); GroupEntity entity = (GroupEntity)getGroup(groupPosition); text_group_cotent.setText(entity.groupName); return convertView; } @Override public boolean hasStableIds() { // TODO Auto-generated method stub return true; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { // TODO Auto-generated method stub return true; } }所以,当在MainActivity中通过调用parseToBean方法完成解析xml数据后,将解析得到的实体类填充到适配器中,然后通过ExpandableListView显示出来。工程中的ViewHolder是自定义类,它的存在,是为了避免在Adapter类中频繁地创建ViewHolder。
7.ViewHolder.java文件代码如下:
package com.steven.android.sax.xml.custom; import android.util.SparseArray; import android.view.View; public class ViewHolder { @SuppressWarnings("unchecked") public static <T extends View> T get(View view, int id) { SparseArray<View> viewHolder = (SparseArray<View>) view.getTag(); if (viewHolder == null) { viewHolder = new SparseArray<View>(); view.setTag(viewHolder); } View childView = viewHolder.get(id); if (childView == null) { childView = view.findViewById(id); viewHolder.put(id, childView); } return (T) childView; } }
二。SAX解析xml格式数据。
前面介绍了如何借助simple-xml包解析xml数据。这里,将要介绍不需要通过第三方jar包,如何通过SAX有效地去解析xml数据。关于SAX的介绍,笔者在这里就不再累赘了,相信很多程序猿都接触过了。
下面是整个Demo工程文件截图,如下图:
该工程代码和simple-xml工程代码一样,也是将解析的xml数据通过ExpandableListView显示出来。assets目录中的data.xml文件内容、ExpandAdapter类、相关文件布局和simple-xml工程差不多都是一样的,这里就不贴出来了。不过实体类是有变化的, 不再是公共成员变量形式存在,而是私有变量形式存在,以set、get形式赋值和取值。下面看看实体类的代码。
1.GroupEntity.java文件代码如下:
package com.steven.android.sax.xml.entity; import java.util.ArrayList; import java.util.List; public class GroupEntity { private String groupId; private String groupName; private List<MemberEntity> memberEntities = new ArrayList<MemberEntity>();; public String getGroupId() { return groupId; } public void setGroupId(String groupId) { this.groupId = groupId; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public List<MemberEntity> getMemberEntities() { return memberEntities; } public void setMemberEntities(List<MemberEntity> memberEntities) { this.memberEntities = memberEntities; } }2.MemberEntity.java文件代码如下:
package com.steven.android.sax.xml.entity; public class MemberEntity { private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }接下来,我们看看主页面的代码。
3.MainActivity.java文件代码如下:
package com.steven.android.sax.xml.activity; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.widget.ExpandableListView; import com.steven.android.sax.xml.adapter.ExpandAdapter; import com.steven.android.sax.xml.entity.GroupEntity; import com.steven.android.sax.xml.handler.DataParseHandler; import com.steven.android.sax.xml.util.XmlParserUtil; /** * 描述:主页面 * @author stevenhu223 * */ public class MainActivity extends Activity { private ExpandableListView mExpandableListView; private ExpandAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mExpandableListView = (ExpandableListView) findViewById(R.id.expanlist_content); try { matchAndParseXmlData(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /** * 匹配获取和解析xml文件内容 * @throws Exception */ private void matchAndParseXmlData() throws Exception { InputStream inputStream = getResources().getAssets().open("data.xml"); String dataContent = convertStreamToString(inputStream); String content = ""; Pattern DATA_PATTERN= Pattern.compile("[\\S\\s]*(<dataContent>[\\s\\S]*</dataContent>)[\\s\\S]*"); Matcher matcher = DATA_PATTERN.matcher(dataContent); if (matcher.matches()) { content = matcher.group(1); } if (!TextUtils.isEmpty(content)) { DataParseHandler handler = new DataParseHandler(); XmlParserUtil.parserXMLByHandler(handler, content); List<GroupEntity> mGroupEntities = handler.getResult(); mAdapter = new ExpandAdapter(this, mGroupEntities); mExpandableListView.setAdapter(mAdapter); } } /** * 输入流转字符串 * @param is * @return */ public String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }在MainActivity中,matchAndParseData方法实现SAX解析xml数据。SAX解析xml数据,其实重点是如何创建继承DefaultHandler2的类。我们来看看工程中创建的DataParseHandler类。
4.DataParseHandler.java文件代码如下:
package com.steven.android.sax.xml.handler; import java.util.ArrayList; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.ext.DefaultHandler2; import com.steven.android.sax.xml.entity.GroupEntity; import com.steven.android.sax.xml.entity.MemberEntity; /** * 描述:data.xml文件内容解析handler</br> * * @author stevenhu223 */ public class DataParseHandler extends DefaultHandler2 { InputSource mInputSource; String nodeName; public GroupEntity groupEntity; public MemberEntity memberEntity; public ArrayList<GroupEntity> groupEntities; StringBuffer cData;// 某一段cdata的值 public DataParseHandler() { cData = new StringBuffer(); groupEntities = new ArrayList<GroupEntity>(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (nodeName != null && nodeName.equals("groupID")) { String data = new String(ch, start, length); cData.append(data); super.characters(ch, start, length); } else if (nodeName != null && nodeName.equals("groupName")) { String data = new String(ch, start, length); cData.append(data); super.characters(ch, start, length); } else if (nodeName != null && nodeName.equals("name")) { String data = new String(ch, start, length); cData.append(data); super.characters(ch, start, length); } else if (nodeName != null && nodeName.equals("age")) { String data = new String(ch, start, length); cData.append(data); super.characters(ch, start, length); } } @Override public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException { nodeName = localName; if (localName.equals("group")) { //读到group开始元素时创建GroupEntity对象 groupEntity = new GroupEntity(); } else if (localName.equals("member")){ //读到member开始元素时创建MemberEntity对象 memberEntity = new MemberEntity(); } else if (localName.equals("groupID")) { startCDATA(); } else if (localName.equals("groupName")) { startCDATA(); } else if (localName.equals("name")) { startCDATA(); } else if (localName.equals("age")) { startCDATA(); } } @Override public void endElement(String uri, String localName, String name) throws SAXException { nodeName = null; if (localName.equals("group")) { //读到group结束元素时添加GroupEntity对象添加到集合 groupEntities.add(groupEntity); } else if (localName.equals("member")) { //读到member结束元素时将MemberEntity对象添加到集合 groupEntity.getMemberEntities().add(memberEntity); } else if (localName.equals("groupID")) { endCDATA(); groupEntity.setGroupId(getCDataString()); } else if (localName.equals("groupName")) { endCDATA(); groupEntity.setGroupName(getCDataString()); } else if (localName.equals("name")) { endCDATA(); memberEntity.setName(getCDataString()); } else if (localName.equals("age")) { endCDATA(); memberEntity.setAge(getCDataString()); } } private String getCDataString() { return cData.toString(); } // 重新开始CDATA @Override public void startCDATA() throws SAXException { if (cData == null) { cData = new StringBuffer(); } else { cData.delete(0, cData.length()); } super.startCDATA(); } @Override public void endCDATA() throws SAXException { super.endCDATA(); } public ArrayList<GroupEntity> getResult() { return groupEntities; } }通过 DataParseHandler的getResult()方法可以获取到解析xml数据成功后的实体集合。在创xml解析数据对应的DataParseHandler类后,还需要将该类的对象和需要解析的xml数据关联起来,于是就有了XmlParserUtil工具类。
5.XmlParserUtil.java文件代码如下:
package com.steven.android.sax.xml.util; import java.io.StringReader; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; /** * 描述:Sax解析工具类 * @author stevenhu223 * */ public class XmlParserUtil { /** * 关联DefaultHandler2和xml数据进行解析 * @param handler * @param xml */ public static void parserXMLByHandler(DefaultHandler2 handler,String xml) { XMLReader xmlReader; InputSource input = getInputSouceByString(xml); try { SAXParserFactory s = SAXParserFactory.newInstance(); xmlReader = s.newSAXParser().getXMLReader(); xmlReader.setContentHandler(handler); xmlReader.parse(input); } catch (Exception e) { e.printStackTrace(); } } /** * 通过字符串获取流 * @param xmlStr * @return */ public static InputSource getInputSouceByString(String xmlStr) { StringReader sr = new StringReader(xmlStr); InputSource is = new InputSource(sr); return is; } }
所以,通过创建对应的DataParseHandler与XmlParserUtil关联起来就可以完成解析xml数据了。
小结:关于SAX解析xml数据。比较麻烦的是,每份需要解析的xml数据对应的都需要创建相应的DefaultHandler2类,如果App后台接口较多的话,需要创建的解析后台数据的DefaultHandler2类也就相应的增多,这样会给App的维护带来一定的弊端。这种情况下建议还是使用simple-xml解析,毕竟simple-xml包也不大,也就418KB而已。笔者就经常使用simple-xml包解析xml数据。
三。jackson包解析json格式数据
上面讲解的是xml数据解析,接下来将谈谈json数据的解析,json数据的解析有很多种方式。当然,我个人比较喜欢的是jackson包对Json数据的解析,jackson包相对来说比较大一点,有1MB以上,不过速度快,效率高,性能72个赞。这个就是笔者比较青睐它的原因。当然了,有时候考虑到工程的大小,也不得不考虑其他方式的解析,google也提供了一些json解析的工具包,这里也不再一一介绍,有兴趣可以去google官网去了解了解。这里主要还是介绍jackson的解析,不喜欢的可以绕道绕道咯。jackson的官网地址为:http://jackson.codehaus.org/,相关的jar包可以到官网上下载。
下面是整个Demo工程文件截图,如下图:
同样的,该工程也是在simple-xml工程的基础上去做处理,也是将解析后的数据通过ExpandableListView显示出来。相同的类,这里就不在贴出来了。不过相关的实体类会有变化。assets目录中的jsonData文件内容为json格式。内容和simple-xml工程中的data.xml文件内容一样,只不过是json格式,我们来看看jsonData文件内容。
1.jsonData文件内容如下(注意:将jsonData文件的编码格式设置为UTF-8,否则文件将出现乱编吗):
{ "dataContent": { "group": [ { "groupID": "1", "groupName": "第一组", "member": [ { "name": "张三", "age": "22" }, { "name": "李四", "age": "24" }, { "name": "欧阳雪", "age": "18" } ] }, { "groupID": "2", "groupName": "第二组", "member": [ { "name": "司徒静", "age": "19" }, { "name": "叶笙", "age": "26" }, { "name": "杨风", "age": "25" } ] }, { "groupID": "3", "groupName": "第三组", "member": [ { "name": "王龙", "age": "32" }, { "name": "西门胜男", "age": "21" }, { "name": "张铬", "age": "45" } ] } ] } }
接下来,我们看看主页面的代码。
2.MainActivity.java文件代码如下:
package com.steven.android.jackson.activity; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.ExpandableListView; import com.steven.android.jackson.adapter.ExpandAdapter; import com.steven.android.jackson.entity.JsonResponseEntity; /** * 描述:主页面 * @author stevenhu223 * */ public class MainActivity extends Activity { private ExpandableListView mExpandableListView; private ExpandAdapter mAdapter; private ObjectMapper mObjectMapper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mExpandableListView = (ExpandableListView) findViewById(R.id.expanlist_content); mObjectMapper = new ObjectMapper(); try { parseJsonData(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /** * json数据格式解析 * @throws Exception */ private void parseJsonData() throws Exception{ InputStream inputStream = getResources().getAssets().open("jsonData"); String dataContent = convertStreamToString(inputStream); try { JsonResponseEntity datEntity = mObjectMapper.readValue(dataContent, new TypeReference<JsonResponseEntity>() { }); mAdapter = new ExpandAdapter(this, datEntity.getDataContent().getGroup()); mExpandableListView.setAdapter(mAdapter); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } /** * 输入流转字符串 * @param is * @return */ public String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }代码中,parseJsonData方法实现jackson解析json格式数据,ObjectMapper来自jackson包,通过调用mObjectMapper对象readValue函数就可以实现对json数据的解析。我们来看看JsonResponseEntity实体类的代码。
3.JsonResponseEntity.java文件代码如下:
package com.steven.android.jackson.entity; public class JsonResponseEntity { /** * jackson解析有严格的规定,变量名要和对应的元素名一致,否则解析会时会报错 */ private DataContentEntity dataContent; public DataContentEntity getDataContent() { return dataContent; } public void setDataContent(DataContentEntity dataContent) { this.dataContent = dataContent; } }值得注意的是,jackson解析有严格的实体类变量名对应json数据中的key名相同的限制,如果不一致,解析将会有问题。变量名dataContent对应的就是jsonData文件内容中的第一个key(dataContent);接下来来列出的其他实体类中的变量名,集合名都要和jsonData文件内容中的一致。
package com.steven.android.jackson.entity; import java.util.List; public class DataContentEntity { //变量名对应json内容中的group private List<GroupEntity> group; public List<GroupEntity> getGroup() { return group; } public void setGroup(List<GroupEntity> group) { this.group = group; } }5.GroupEntity文件代码如下:
package com.steven.android.jackson.entity; import java.util.ArrayList; import java.util.List; public class GroupEntity { private String groupID; //变量名对应json内容中的groupID private String groupName; //变量名对应json内容中的groupName //变量名对应json内容中的member private List<MemberEntity> member = new ArrayList<MemberEntity>(); public String getGroupID() { return groupID; } public void setGroupID(String groupID) { this.groupID = groupID; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public List<MemberEntity> getMember() { return member; } public void setMember(List<MemberEntity> member) { this.member = member; } }6.MemberEntity.java文件代码如下:
package com.steven.android.jackson.entity; public class MemberEntity { private String name; //变量名对应json内容中的name private String age; //变量名对应json内容中的age public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }以上为jackson解析相关的实体类。通过MainActivity的parseJson方法就可以将json数据解析成封装的DataJsonResponseEntity了。
四。jackson数据转换解析
jackson包不仅仅是单纯的解析json格式数据,还可以双向解析,甚至可以将json数据解析成map映射等。接下来将主要介绍Jackson包的json与bean(实体类)、Map与json之间的双向解析。
下面是整个Demo工程文件截图,如下图:
工程中,assets目录中的jsonData文件内容为一些相关销售报表数据。
1.jsonData文件内容如下(注意:将jsonData文件的编码格式设置为UTF-8,否则文件将出现乱编吗):
{ "retCode": "0", "retMsg": "success", "chart": { "caption": "2014季度销售报表汇总", "subcaption": "2014季度", "xaxisname": "销售月份", "yaxisname": "销售额度", "numberprefix": "$" }, "data": [ { "label": "一月", "value": "17400" }, { "label": "二月", "value": "19800" }, { "label": "三月", "value": "21800" }, { "label": "四月", "value": "23800" }, { "label": "五月", "value": "29600" }, { "label": "六月", "value": "27600" }, { "label": "七月", "value": "31800" }, { "label": "八月", "value": "39700" }, { "label": "九月", "value": "37800" }, { "label": "十月", "value": "21900" }, { "label": "十一月", "value": "32900" }, { "label": "十二月", "value": "39800" } ] }2.MainActivity.java文件代码如下:
package com.stevenhu.android.jacksontest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import com.stevenhu.android.jacksontest.bean.ChartsDataEntity; import com.stevenhu.android.jacksontest.bean.ChartsEntity; import com.stevenhu.android.jacksontest.bean.DataSetEntity; public class MainActivity extends Activity{ private String jsonData; private String mResult; private TextView text_content_show; private ChartsDataEntity mChartsDataEntity; private ObjectMapper mObjectMapper; private List<DataSetEntity> mDataSets; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { initialize(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } initBean(); text_content_show.setText(parseMapToJson()); } /** * 初始化 */ private void initialize() throws Exception{ text_content_show = (TextView)findViewById(R.id.text_content_show); InputStream inputStream = getResources().getAssets().open("jsonData"); jsonData = convertStreamToString(inputStream); } /** * 输入流转字符串 * @param is * @return */ public String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } /** * 初始化Bean */ private void initBean() { mObjectMapper = new ObjectMapper(); mChartsDataEntity = new ChartsDataEntity(); mDataSets = new ArrayList<DataSetEntity>(); //ChartsEntity对象定义了图表属性 ChartsEntity chart = new ChartsEntity(); chart.setCaption("2014季度销售报表汇总"); chart.setSubcaption("2014季度"); chart.setXaxisname("销售月份"); chart.setYaxisname("销售额度"); chart.setNumberprefix("$"); mChartsDataEntity.setChart(chart); initDataSet("一月", "17400"); initDataSet("二月", "19800"); initDataSet("三月", "21800"); initDataSet("四月", "23800"); initDataSet("五月", "29600"); initDataSet("六月", "27600"); initDataSet("七月", "31800"); initDataSet("八月", "39700"); initDataSet("九月", "37800"); initDataSet("十月", "21900"); initDataSet("十一月", "32900"); initDataSet("十二月", "39800"); initDataSet("一月", "17400"); } /** * 初始化DataSet * @param month * @param sale */ private void initDataSet(String month, String sale) { //DataSetEntity对象定义了图表的一组数据 DataSetEntity dataSet = new DataSetEntity(); dataSet.setLabel(month); dataSet.setValue(sale); mDataSets.add(dataSet); mChartsDataEntity.setData(mDataSets); } /** * json数据格式转map * @return */ private String parseJsonToMap() { String jsonString = "{\"name\":\"2014季度销售报表汇总\",\"chart\":{\"caption\":\"2014季度销售报表汇总\"," + " \"subcaption\":\"2014季度\",\"xaxisname\":\"销售月份\", \"yaxisname\":\"销售额度\", \"numberprefix\":\"$\"}}"; if (null != mResult) { mResult = ""; } try { Map<String , Map<String , Object>> maps = mObjectMapper.readValue(jsonString, Map.class); Set<String> keys = maps.keySet(); Iterator<String> iterator = keys.iterator(); while (iterator.hasNext()) { String key = iterator.next(); mResult += key + ":" + maps.get(key) + "\n"; } return mResult; } catch (Exception e) { e.printStackTrace(); } return null; } /** * map转json格式数据 * @return */ private String parseMapToJson() { Map<String , Object> map = new HashMap<String , Object>(); String chartTitle = mChartsDataEntity.getChart().getCaption(); map.put("name", chartTitle); map.put("chart", mChartsDataEntity.getChart()); try { StringWriter sw = new StringWriter(); JsonGenerator jsonGenerator = mObjectMapper.getJsonFactory().createJsonGenerator(sw); jsonGenerator.writeObject(map); jsonGenerator.close(); String json = sw.toString(); return json; } catch (Exception e) { // TODO: handle exception } return null; } /** * json数据格式转实体类 * @return */ private String parseJsonToBean() { try { ChartsDataEntity chartsData = mObjectMapper.readValue(jsonData, new TypeReference<ChartsDataEntity>() { }); ChartsEntity charts = chartsData.getChart(); //String name = chartsData.getName(); mResult = "RetCode-->" + chartsData.getRetCode() + "\n" + "RetMsg-->" + chartsData.getRetMsg() + "\n" + "caption-->" + charts.getCaption() + "\n" + "subcaption-->" + charts.getSubcaption() + "\n" + "xaxisname-->" + charts.getXaxisname() + "\n" + "yaxisname-->" + charts.getYaxisname() + "\n" + "numberprefix-->" + charts.getNumberprefix(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } List<DataSetEntity> datas = mChartsDataEntity.getData(); for (DataSetEntity dataSet : datas) { mResult += "\n" + "label-->" + dataSet.getLabel() + " " + "value-->" + dataSet.getValue(); } return mResult; } /** * 实体类转json格式数据 * @return */ private String parseBeanToJson() { try { StringWriter sw = new StringWriter(); JsonGenerator jsonGenerator = mObjectMapper.getJsonFactory().createJsonGenerator(sw); //objectMapper.writeValue(jsonGenerator, mChartsDataEntity); jsonGenerator.writeObject(mChartsDataEntity); jsonGenerator.close(); String json = sw.toString(); return json; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return null; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item_map_to_json: text_content_show.setText(parseMapToJson()); break; case R.id.item_json_to_map: text_content_show.setText(parseJsonToMap()); break; case R.id.item_bean_to_json: text_content_show.setText(parseBeanToJson()); break; case R.id.item_json_to_bean: text_content_show.setText(parseJsonToBean()); break; } return true; } }在MainActvity中,通过parseMapToJson、parseJsonToMap、parseBeanToJson、parseJsonToBean等方法实现json与bean、map与json之间的解析转换。其他相关的解析实体类的代码就不贴出来了,原理都是一样的。